{@}blendmodes.glsl{@}float blendColorDodge(float base, float blend) {
    return (blend == 1.0)?blend:min(base/(1.0-blend), 1.0);
}
vec3 blendColorDodge(vec3 base, vec3 blend) {
    return vec3(blendColorDodge(base.r, blend.r), blendColorDodge(base.g, blend.g), blendColorDodge(base.b, blend.b));
}
vec3 blendColorDodge(vec3 base, vec3 blend, float opacity) {
    return (blendColorDodge(base, blend) * opacity + base * (1.0 - opacity));
}
float blendColorBurn(float base, float blend) {
    return (blend == 0.0)?blend:max((1.0-((1.0-base)/blend)), 0.0);
}
vec3 blendColorBurn(vec3 base, vec3 blend) {
    return vec3(blendColorBurn(base.r, blend.r), blendColorBurn(base.g, blend.g), blendColorBurn(base.b, blend.b));
}
vec3 blendColorBurn(vec3 base, vec3 blend, float opacity) {
    return (blendColorBurn(base, blend) * opacity + base * (1.0 - opacity));
}
float blendVividLight(float base, float blend) {
    return (blend<0.5)?blendColorBurn(base, (2.0*blend)):blendColorDodge(base, (2.0*(blend-0.5)));
}
vec3 blendVividLight(vec3 base, vec3 blend) {
    return vec3(blendVividLight(base.r, blend.r), blendVividLight(base.g, blend.g), blendVividLight(base.b, blend.b));
}
vec3 blendVividLight(vec3 base, vec3 blend, float opacity) {
    return (blendVividLight(base, blend) * opacity + base * (1.0 - opacity));
}
float blendHardMix(float base, float blend) {
    return (blendVividLight(base, blend)<0.5)?0.0:1.0;
}
vec3 blendHardMix(vec3 base, vec3 blend) {
    return vec3(blendHardMix(base.r, blend.r), blendHardMix(base.g, blend.g), blendHardMix(base.b, blend.b));
}
vec3 blendHardMix(vec3 base, vec3 blend, float opacity) {
    return (blendHardMix(base, blend) * opacity + base * (1.0 - opacity));
}
float blendLinearDodge(float base, float blend) {
    return min(base+blend, 1.0);
}
vec3 blendLinearDodge(vec3 base, vec3 blend) {
    return min(base+blend, vec3(1.0));
}
vec3 blendLinearDodge(vec3 base, vec3 blend, float opacity) {
    return (blendLinearDodge(base, blend) * opacity + base * (1.0 - opacity));
}
float blendLinearBurn(float base, float blend) {
    return max(base+blend-1.0, 0.0);
}
vec3 blendLinearBurn(vec3 base, vec3 blend) {
    return max(base+blend-vec3(1.0), vec3(0.0));
}
vec3 blendLinearBurn(vec3 base, vec3 blend, float opacity) {
    return (blendLinearBurn(base, blend) * opacity + base * (1.0 - opacity));
}
float blendLinearLight(float base, float blend) {
    return blend<0.5?blendLinearBurn(base, (2.0*blend)):blendLinearDodge(base, (2.0*(blend-0.5)));
}
vec3 blendLinearLight(vec3 base, vec3 blend) {
    return vec3(blendLinearLight(base.r, blend.r), blendLinearLight(base.g, blend.g), blendLinearLight(base.b, blend.b));
}
vec3 blendLinearLight(vec3 base, vec3 blend, float opacity) {
    return (blendLinearLight(base, blend) * opacity + base * (1.0 - opacity));
}
float blendLighten(float base, float blend) {
    return max(blend, base);
}
vec3 blendLighten(vec3 base, vec3 blend) {
    return vec3(blendLighten(base.r, blend.r), blendLighten(base.g, blend.g), blendLighten(base.b, blend.b));
}
vec3 blendLighten(vec3 base, vec3 blend, float opacity) {
    return (blendLighten(base, blend) * opacity + base * (1.0 - opacity));
}
float blendDarken(float base, float blend) {
    return min(blend, base);
}
vec3 blendDarken(vec3 base, vec3 blend) {
    return vec3(blendDarken(base.r, blend.r), blendDarken(base.g, blend.g), blendDarken(base.b, blend.b));
}
vec3 blendDarken(vec3 base, vec3 blend, float opacity) {
    return (blendDarken(base, blend) * opacity + base * (1.0 - opacity));
}
float blendPinLight(float base, float blend) {
    return (blend<0.5)?blendDarken(base, (2.0*blend)):blendLighten(base, (2.0*(blend-0.5)));
}
vec3 blendPinLight(vec3 base, vec3 blend) {
    return vec3(blendPinLight(base.r, blend.r), blendPinLight(base.g, blend.g), blendPinLight(base.b, blend.b));
}
vec3 blendPinLight(vec3 base, vec3 blend, float opacity) {
    return (blendPinLight(base, blend) * opacity + base * (1.0 - opacity));
}
float blendReflect(float base, float blend) {
    return (blend == 1.0)?blend:min(base*base/(1.0-blend), 1.0);
}
vec3 blendReflect(vec3 base, vec3 blend) {
    return vec3(blendReflect(base.r, blend.r), blendReflect(base.g, blend.g), blendReflect(base.b, blend.b));
}
vec3 blendReflect(vec3 base, vec3 blend, float opacity) {
    return (blendReflect(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendGlow(vec3 base, vec3 blend) {
    return blendReflect(blend, base);
}
vec3 blendGlow(vec3 base, vec3 blend, float opacity) {
    return (blendGlow(base, blend) * opacity + base * (1.0 - opacity));
}
float blendOverlay(float base, float blend) {
    return base<0.5?(2.0*base*blend):(1.0-2.0*(1.0-base)*(1.0-blend));
}
vec3 blendOverlay(vec3 base, vec3 blend) {
    return vec3(blendOverlay(base.r, blend.r), blendOverlay(base.g, blend.g), blendOverlay(base.b, blend.b));
}
vec3 blendOverlay(vec3 base, vec3 blend, float opacity) {
    return (blendOverlay(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendHardLight(vec3 base, vec3 blend) {
    return blendOverlay(blend, base);
}
vec3 blendHardLight(vec3 base, vec3 blend, float opacity) {
    return (blendHardLight(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendPhoenix(vec3 base, vec3 blend) {
    return min(base, blend)-max(base, blend)+vec3(1.0);
}
vec3 blendPhoenix(vec3 base, vec3 blend, float opacity) {
    return (blendPhoenix(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendNormal(vec3 base, vec3 blend) {
    return blend;
}
vec3 blendNormal(vec3 base, vec3 blend, float opacity) {
    return (blendNormal(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendNegation(vec3 base, vec3 blend) {
    return vec3(1.0)-abs(vec3(1.0)-base-blend);
}
vec3 blendNegation(vec3 base, vec3 blend, float opacity) {
    return (blendNegation(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendMultiply(vec3 base, vec3 blend) {
    return base*blend;
}
vec3 blendMultiply(vec3 base, vec3 blend, float opacity) {
    return (blendMultiply(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendAverage(vec3 base, vec3 blend) {
    return (base+blend)/2.0;
}
vec3 blendAverage(vec3 base, vec3 blend, float opacity) {
    return (blendAverage(base, blend) * opacity + base * (1.0 - opacity));
}
float blendScreen(float base, float blend) {
    return 1.0-((1.0-base)*(1.0-blend));
}
vec3 blendScreen(vec3 base, vec3 blend) {
    return vec3(blendScreen(base.r, blend.r), blendScreen(base.g, blend.g), blendScreen(base.b, blend.b));
}
vec3 blendScreen(vec3 base, vec3 blend, float opacity) {
    return (blendScreen(base, blend) * opacity + base * (1.0 - opacity));
}
float blendSoftLight(float base, float blend) {
    return (blend<0.5)?(2.0*base*blend+base*base*(1.0-2.0*blend)):(sqrt(base)*(2.0*blend-1.0)+2.0*base*(1.0-blend));
}
vec3 blendSoftLight(vec3 base, vec3 blend) {
    return vec3(blendSoftLight(base.r, blend.r), blendSoftLight(base.g, blend.g), blendSoftLight(base.b, blend.b));
}
vec3 blendSoftLight(vec3 base, vec3 blend, float opacity) {
    return (blendSoftLight(base, blend) * opacity + base * (1.0 - opacity));
}
float blendSubtract(float base, float blend) {
    return max(base+blend-1.0, 0.0);
}
vec3 blendSubtract(vec3 base, vec3 blend) {
    return max(base+blend-vec3(1.0), vec3(0.0));
}
vec3 blendSubtract(vec3 base, vec3 blend, float opacity) {
    return (blendSubtract(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendExclusion(vec3 base, vec3 blend) {
    return base+blend-2.0*base*blend;
}
vec3 blendExclusion(vec3 base, vec3 blend, float opacity) {
    return (blendExclusion(base, blend) * opacity + base * (1.0 - opacity));
}
vec3 blendDifference(vec3 base, vec3 blend) {
    return abs(base-blend);
}
vec3 blendDifference(vec3 base, vec3 blend, float opacity) {
    return (blendDifference(base, blend) * opacity + base * (1.0 - opacity));
}
float blendAdd(float base, float blend) {
    return min(base+blend, 1.0);
}
vec3 blendAdd(vec3 base, vec3 blend) {
    return min(base+blend, vec3(1.0));
}
vec3 blendAdd(vec3 base, vec3 blend, float opacity) {
    return (blendAdd(base, blend) * opacity + base * (1.0 - opacity));
}{@}matcap.vs{@}vec2 reflectMatcap(vec3 position, mat4 modelViewMatrix, mat3 normalMatrix, vec3 normal) {
    vec4 p = vec4(position, 1.0);
    
    vec3 e = normalize(vec3(modelViewMatrix * p));
    vec3 n = normalize(normalMatrix * normal);
    vec3 r = reflect(e, n);
    float m = 2.0 * sqrt(
        pow(r.x, 2.0) +
        pow(r.y, 2.0) +
        pow(r.z + 1.0, 2.0)
    );
    
    vec2 uv = r.xy / m + .5;
    
    return uv;
}

vec2 reflectMatcap(vec3 position, mat4 modelViewMatrix, vec3 normal) {
    vec4 p = vec4(position, 1.0);
    
    vec3 e = normalize(vec3(modelViewMatrix * p));
    vec3 n = normalize(normal);
    vec3 r = reflect(e, n);
    float m = 2.0 * sqrt(
                         pow(r.x, 2.0) +
                         pow(r.y, 2.0) +
                         pow(r.z + 1.0, 2.0)
                         );
    
    vec2 uv = r.xy / m + .5;
    
    return uv;
}

vec2 reflectMatcap(vec4 mvPos, vec3 normal) {
    vec3 e = normalize(vec3(mvPos));
    vec3 n = normalize(normal);
    vec3 r = reflect(e, n);
    float m = 2.0 * sqrt(
                         pow(r.x, 2.0) +
                         pow(r.y, 2.0) +
                         pow(r.z + 1.0, 2.0)
                         );

    vec2 uv = r.xy / m + .5;

    return uv;
}{@}AntimatterCopy.fs{@}uniform sampler2D tDiffuse;

varying vec2 vUv;

void main() {
    gl_FragColor = texture2D(tDiffuse, vUv);
}{@}AntimatterCopy.vs{@}varying vec2 vUv;
void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}{@}AntimatterPass.vs{@}varying vec2 vUv;

void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}{@}AntimatterPosition.vs{@}uniform sampler2D tPos;

void main() {
    vec4 decodedPos = texture2D(tPos, position.xy);
    vec3 pos = decodedPos.xyz;

    vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
    gl_PointSize = 0.02 * (1000.0 / length(mvPosition.xyz));
    gl_Position = projectionMatrix * mvPosition;
}{@}AntimatterBasicFrag.fs{@}void main() {
    gl_FragColor = vec4(1.0);
}{@}antimatter.glsl{@}vec3 getData(sampler2D tex, vec2 uv) {
    return texture2D(tex, uv).xyz;
}

vec4 getData4(sampler2D tex, vec2 uv) {
    return texture2D(tex, uv);
}

{@}conditionals.glsl{@}vec4 when_eq(vec4 x, vec4 y) {
  return 1.0 - abs(sign(x - y));
}

vec4 when_neq(vec4 x, vec4 y) {
  return abs(sign(x - y));
}

vec4 when_gt(vec4 x, vec4 y) {
  return max(sign(x - y), 0.0);
}

vec4 when_lt(vec4 x, vec4 y) {
  return max(sign(y - x), 0.0);
}

vec4 when_ge(vec4 x, vec4 y) {
  return 1.0 - when_lt(x, y);
}

vec4 when_le(vec4 x, vec4 y) {
  return 1.0 - when_gt(x, y);
}

vec3 when_eq(vec3 x, vec3 y) {
  return 1.0 - abs(sign(x - y));
}

vec3 when_neq(vec3 x, vec3 y) {
  return abs(sign(x - y));
}

vec3 when_gt(vec3 x, vec3 y) {
  return max(sign(x - y), 0.0);
}

vec3 when_lt(vec3 x, vec3 y) {
  return max(sign(y - x), 0.0);
}

vec3 when_ge(vec3 x, vec3 y) {
  return 1.0 - when_lt(x, y);
}

vec3 when_le(vec3 x, vec3 y) {
  return 1.0 - when_gt(x, y);
}

vec2 when_eq(vec2 x, vec2 y) {
  return 1.0 - abs(sign(x - y));
}

vec2 when_neq(vec2 x, vec2 y) {
  return abs(sign(x - y));
}

vec2 when_gt(vec2 x, vec2 y) {
  return max(sign(x - y), 0.0);
}

vec2 when_lt(vec2 x, vec2 y) {
  return max(sign(y - x), 0.0);
}

vec2 when_ge(vec2 x, vec2 y) {
  return 1.0 - when_lt(x, y);
}

vec2 when_le(vec2 x, vec2 y) {
  return 1.0 - when_gt(x, y);
}

float when_eq(float x, float y) {
  return 1.0 - abs(sign(x - y));
}

float when_neq(float x, float y) {
  return abs(sign(x - y));
}

float when_gt(float x, float y) {
  return max(sign(x - y), 0.0);
}

float when_lt(float x, float y) {
  return max(sign(y - x), 0.0);
}

float when_ge(float x, float y) {
  return 1.0 - when_lt(x, y);
}

float when_le(float x, float y) {
  return 1.0 - when_gt(x, y);
}

vec4 and(vec4 a, vec4 b) {
  return a * b;
}

vec4 or(vec4 a, vec4 b) {
  return min(a + b, 1.0);
}

vec4 Not(vec4 a) {
  return 1.0 - a;
}

vec3 and(vec3 a, vec3 b) {
  return a * b;
}

vec3 or(vec3 a, vec3 b) {
  return min(a + b, 1.0);
}

vec3 Not(vec3 a) {
  return 1.0 - a;
}

vec2 and(vec2 a, vec2 b) {
  return a * b;
}

vec2 or(vec2 a, vec2 b) {
  return min(a + b, 1.0);
}


vec2 Not(vec2 a) {
  return 1.0 - a;
}

float and(float a, float b) {
  return a * b;
}

float or(float a, float b) {
  return min(a + b, 1.0);
}

float Not(float a) {
  return 1.0 - a;
}{@}curl.glsl{@}#test Device.mobile
float sinf2(float x) {
    x*=0.159155;
    x-=floor(x);
    float xx=x*x;
    float y=-6.87897;
    y=y*xx+33.7755;
    y=y*xx-72.5257;
    y=y*xx+80.5874;
    y=y*xx-41.2408;
    y=y*xx+6.28077;
    return x*y;
}

float cosf2(float x) {
    return sinf2(x+1.5708);
}
#endtest

#test !Device.mobile
    #define sinf2 sin
    #define cosf2 cos
#endtest

float potential1(vec3 v) {
    float noise = 0.0;
    noise += sinf2(v.x * 1.8 + v.z * 3.) + sinf2(v.x * 4.8 + v.z * 4.5) + sinf2(v.x * -7.0 + v.z * 1.2) + sinf2(v.x * -5.0 + v.z * 2.13);
    noise += sinf2(v.y * -0.48 + v.z * 5.4) + sinf2(v.y * 2.56 + v.z * 5.4) + sinf2(v.y * 4.16 + v.z * 2.4) + sinf2(v.y * -4.16 + v.z * 1.35);
    return noise;
}

float potential2(vec3 v) {
    float noise = 0.0;
    noise += sinf2(v.y * 1.8 + v.x * 3. - 2.82) + sinf2(v.y * 4.8 + v.x * 4.5 + 74.37) + sinf2(v.y * -7.0 + v.x * 1.2 - 256.72) + sinf2(v.y * -5.0 + v.x * 2.13 - 207.683);
    noise += sinf2(v.z * -0.48 + v.x * 5.4 -125.796) + sinf2(v.z * 2.56 + v.x * 5.4 + 17.692) + sinf2(v.z * 4.16 + v.x * 2.4 + 150.512) + sinf2(v.z * -4.16 + v.x * 1.35 - 222.137);
    return noise;
}

float potential3(vec3 v) {
    float noise = 0.0;
    noise += sinf2(v.z * 1.8 + v.y * 3. - 194.58) + sinf2(v.z * 4.8 + v.y * 4.5 - 83.13) + sinf2(v.z * -7.0 + v.y * 1.2 -845.2) + sinf2(v.z * -5.0 + v.y * 2.13 - 762.185);
    noise += sinf2(v.x * -0.48 + v.y * 5.4 - 707.916) + sinf2(v.x * 2.56 + v.y * 5.4 + -482.348) + sinf2(v.x * 4.16 + v.y * 2.4 + 9.872) + sinf2(v.x * -4.16 + v.y * 1.35 - 476.747);
    return noise;
}

vec3 snoiseVec3( vec3 x ) {
    float s  = potential1(x);
    float s1 = potential2(x);
    float s2 = potential3(x);
    return vec3( s , s1 , s2 );
}

//Analitic derivatives of the potentials for the curl noise, based on: http://weber.itn.liu.se/~stegu/TNM084-2019/bridson-siggraph2007-curlnoise.pdf

float dP3dY(vec3 v) {
    float noise = 0.0;
    noise += 3. * cosf2(v.z * 1.8 + v.y * 3. - 194.58) + 4.5 * cosf2(v.z * 4.8 + v.y * 4.5 - 83.13) + 1.2 * cosf2(v.z * -7.0 + v.y * 1.2 -845.2) + 2.13 * cosf2(v.z * -5.0 + v.y * 2.13 - 762.185);
    noise += 5.4 * cosf2(v.x * -0.48 + v.y * 5.4 - 707.916) + 5.4 * cosf2(v.x * 2.56 + v.y * 5.4 + -482.348) + 2.4 * cosf2(v.x * 4.16 + v.y * 2.4 + 9.872) + 1.35 * cosf2(v.x * -4.16 + v.y * 1.35 - 476.747);
    return noise;
}

float dP2dZ(vec3 v) {
    return -0.48 * cosf2(v.z * -0.48 + v.x * 5.4 -125.796) + 2.56 * cosf2(v.z * 2.56 + v.x * 5.4 + 17.692) + 4.16 * cosf2(v.z * 4.16 + v.x * 2.4 + 150.512) -4.16 * cosf2(v.z * -4.16 + v.x * 1.35 - 222.137);
}

float dP1dZ(vec3 v) {
    float noise = 0.0;
    noise += 3. * cosf2(v.x * 1.8 + v.z * 3.) + 4.5 * cosf2(v.x * 4.8 + v.z * 4.5) + 1.2 * cosf2(v.x * -7.0 + v.z * 1.2) + 2.13 * cosf2(v.x * -5.0 + v.z * 2.13);
    noise += 5.4 * cosf2(v.y * -0.48 + v.z * 5.4) + 5.4 * cosf2(v.y * 2.56 + v.z * 5.4) + 2.4 * cosf2(v.y * 4.16 + v.z * 2.4) + 1.35 * cosf2(v.y * -4.16 + v.z * 1.35);
    return noise;
}

float dP3dX(vec3 v) {
    return -0.48 * cosf2(v.x * -0.48 + v.y * 5.4 - 707.916) + 2.56 * cosf2(v.x * 2.56 + v.y * 5.4 + -482.348) + 4.16 * cosf2(v.x * 4.16 + v.y * 2.4 + 9.872) -4.16 * cosf2(v.x * -4.16 + v.y * 1.35 - 476.747);
}

float dP2dX(vec3 v) {
    float noise = 0.0;
    noise += 3. * cosf2(v.y * 1.8 + v.x * 3. - 2.82) + 4.5 * cosf2(v.y * 4.8 + v.x * 4.5 + 74.37) + 1.2 * cosf2(v.y * -7.0 + v.x * 1.2 - 256.72) + 2.13 * cosf2(v.y * -5.0 + v.x * 2.13 - 207.683);
    noise += 5.4 * cosf2(v.z * -0.48 + v.x * 5.4 -125.796) + 5.4 * cosf2(v.z * 2.56 + v.x * 5.4 + 17.692) + 2.4 * cosf2(v.z * 4.16 + v.x * 2.4 + 150.512) + 1.35 * cosf2(v.z * -4.16 + v.x * 1.35 - 222.137);
    return noise;
}

float dP1dY(vec3 v) {
    return -0.48 * cosf2(v.y * -0.48 + v.z * 5.4) + 2.56 * cosf2(v.y * 2.56 + v.z * 5.4) +  4.16 * cosf2(v.y * 4.16 + v.z * 2.4) -4.16 * cosf2(v.y * -4.16 + v.z * 1.35);
}


vec3 curlNoise( vec3 p ) {

    //A sinf2 or cosf2 call is a trigonometric function, these functions are expensive in the GPU
    //the partial derivatives with approximations require to calculate the snoiseVec3 function 4 times.
    //The previous function evaluate the potentials that include 8 trigonometric functions each.
    //
    //This means that the potentials are evaluated 12 times (4 calls to snoiseVec3 that make 3 potential calls).
    //The whole process call 12 * 8 trigonometric functions, a total of 96 times.


    /*
    const float e = 1e-1;
    vec3 dx = vec3( e   , 0.0 , 0.0 );
    vec3 dy = vec3( 0.0 , e   , 0.0 );
    vec3 dz = vec3( 0.0 , 0.0 , e   );
    vec3 p0 = snoiseVec3(p);
    vec3 p_x1 = snoiseVec3( p + dx );
    vec3 p_y1 = snoiseVec3( p + dy );
    vec3 p_z1 = snoiseVec3( p + dz );
    float x = p_y1.z - p0.z - p_z1.y + p0.y;
    float y = p_z1.x - p0.x - p_x1.z + p0.z;
    float z = p_x1.y - p0.y - p_y1.x + p0.x;
    return normalize( vec3( x , y , z ));
    */


    //The noise that is used to define the potentials is based on analitic functions that are easy to derivate,
    //meaning that the analitic solution would provide a much faster approach with the same visual results.
    //
    //Usinf2g the analitic derivatives the algorithm does not require to evaluate snoiseVec3, instead it uses the
    //analitic partial derivatives from each potential on the corresponding axis, providing a total of
    //36 calls to trigonometric functions, making the analytic evaluation almost 3 times faster than the aproximation method.


    float x = dP3dY(p) - dP2dZ(p);
    float y = dP1dZ(p) - dP3dX(p);
    float z = dP2dX(p) - dP1dY(p);


    return normalize( vec3( x , y , z ));



}{@}depthvalue.fs{@}float getDepthValue(sampler2D tDepth, vec2 uv, float n, float f) {
    vec4 depth = texture2D(tDepth, uv);
    return (2.0 * n) / (f + n - depth.x * (f - n));
}{@}eases.glsl{@}#ifndef PI
#define PI 3.141592653589793
#endif

#ifndef HALF_PI
#define HALF_PI 1.5707963267948966
#endif

float backInOut(float t) {
  float f = t < 0.5
    ? 2.0 * t
    : 1.0 - (2.0 * t - 1.0);

  float g = pow(f, 3.0) - f * sin(f * PI);

  return t < 0.5
    ? 0.5 * g
    : 0.5 * (1.0 - g) + 0.5;
}

float backIn(float t) {
  return pow(t, 3.0) - t * sin(t * PI);
}

float backOut(float t) {
  float f = 1.0 - t;
  return 1.0 - (pow(f, 3.0) - f * sin(f * PI));
}

float bounceOut(float t) {
  const float a = 4.0 / 11.0;
  const float b = 8.0 / 11.0;
  const float c = 9.0 / 10.0;

  const float ca = 4356.0 / 361.0;
  const float cb = 35442.0 / 1805.0;
  const float cc = 16061.0 / 1805.0;

  float t2 = t * t;

  return t < a
    ? 7.5625 * t2
    : t < b
      ? 9.075 * t2 - 9.9 * t + 3.4
      : t < c
        ? ca * t2 - cb * t + cc
        : 10.8 * t * t - 20.52 * t + 10.72;
}

float bounceIn(float t) {
  return 1.0 - bounceOut(1.0 - t);
}

float bounceInOut(float t) {
  return t < 0.5
    ? 0.5 * (1.0 - bounceOut(1.0 - t * 2.0))
    : 0.5 * bounceOut(t * 2.0 - 1.0) + 0.5;
}

float circularInOut(float t) {
  return t < 0.5
    ? 0.5 * (1.0 - sqrt(1.0 - 4.0 * t * t))
    : 0.5 * (sqrt((3.0 - 2.0 * t) * (2.0 * t - 1.0)) + 1.0);
}

float circularIn(float t) {
  return 1.0 - sqrt(1.0 - t * t);
}

float circularOut(float t) {
  return sqrt((2.0 - t) * t);
}

float cubicInOut(float t) {
  return t < 0.5
    ? 4.0 * t * t * t
    : 0.5 * pow(2.0 * t - 2.0, 3.0) + 1.0;
}

float cubicIn(float t) {
  return t * t * t;
}

float cubicOut(float t) {
  float f = t - 1.0;
  return f * f * f + 1.0;
}

float elasticInOut(float t) {
  return t < 0.5
    ? 0.5 * sin(+13.0 * HALF_PI * 2.0 * t) * pow(2.0, 10.0 * (2.0 * t - 1.0))
    : 0.5 * sin(-13.0 * HALF_PI * ((2.0 * t - 1.0) + 1.0)) * pow(2.0, -10.0 * (2.0 * t - 1.0)) + 1.0;
}

float elasticIn(float t) {
  return sin(13.0 * t * HALF_PI) * pow(2.0, 10.0 * (t - 1.0));
}

float elasticOut(float t) {
  return sin(-13.0 * (t + 1.0) * HALF_PI) * pow(2.0, -10.0 * t) + 1.0;
}

float expoInOut(float t) {
  return t == 0.0 || t == 1.0
    ? t
    : t < 0.5
      ? +0.5 * pow(2.0, (20.0 * t) - 10.0)
      : -0.5 * pow(2.0, 10.0 - (t * 20.0)) + 1.0;
}

float expoIn(float t) {
  return t == 0.0 ? t : pow(2.0, 10.0 * (t - 1.0));
}

float expoOut(float t) {
  return t == 1.0 ? t : 1.0 - pow(2.0, -10.0 * t);
}

float linear(float t) {
  return t;
}

float quadraticInOut(float t) {
  float p = 2.0 * t * t;
  return t < 0.5 ? p : -p + (4.0 * t) - 1.0;
}

float quadraticIn(float t) {
  return t * t;
}

float quadraticOut(float t) {
  return -t * (t - 2.0);
}

float quarticInOut(float t) {
  return t < 0.5
    ? +8.0 * pow(t, 4.0)
    : -8.0 * pow(t - 1.0, 4.0) + 1.0;
}

float quarticIn(float t) {
  return pow(t, 4.0);
}

float quarticOut(float t) {
  return pow(t - 1.0, 3.0) * (1.0 - t) + 1.0;
}

float qinticInOut(float t) {
  return t < 0.5
    ? +16.0 * pow(t, 5.0)
    : -0.5 * pow(2.0 * t - 2.0, 5.0) + 1.0;
}

float qinticIn(float t) {
  return pow(t, 5.0);
}

float qinticOut(float t) {
  return 1.0 - (pow(t - 1.0, 5.0));
}

float sineInOut(float t) {
  return -0.5 * (cos(PI * t) - 1.0);
}

float sineIn(float t) {
  return sin((t - 1.0) * HALF_PI) + 1.0;
}

float sineOut(float t) {
  return sin(t * HALF_PI);
}
{@}ColorMaterial.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 color;

#!VARYINGS

#!SHADER: ColorMaterial.vs
void main() {
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: ColorMaterial.fs
void main() {
    gl_FragColor = vec4(color, 1.0);
}{@}DebugCamera.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;

#!VARYINGS
varying vec3 vColor;

#!SHADER: DebugCamera.vs
void main() {
    vColor = mix(uColor, vec3(1.0, 0.0, 0.0), step(position.z, -0.1));
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: DebugCamera.fs
void main() {
    gl_FragColor = vec4(vColor, 1.0);
}{@}ScreenQuad.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;

#!VARYINGS
varying vec2 vUv;

#!SHADER: ScreenQuad.vs
void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}

#!SHADER: ScreenQuad.fs
void main() {
    gl_FragColor = texture2D(tMap, vUv);
    gl_FragColor.a = 1.0;
}{@}TestMaterial.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform float alpha;

#!VARYINGS
varying vec3 vNormal;

#!SHADER: TestMaterial.vs
void main() {
    vec3 pos = position;
    vNormal = normalMatrix * normal;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: TestMaterial.fs
void main() {
    gl_FragColor = vec4(vNormal, 1.0);
}{@}TextureMaterial.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;

#!VARYINGS
varying vec2 vUv;

#!SHADER: TextureMaterial.vs
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: TextureMaterial.fs
void main() {
    gl_FragColor = texture2D(tMap, vUv);
    gl_FragColor.rgb /= gl_FragColor.a;
}{@}BlitPass.fs{@}void main() {
    gl_FragColor = texture2D(tDiffuse, vUv);
    gl_FragColor.a = 1.0;
}{@}NukePass.vs{@}varying vec2 vUv;

void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}{@}ShadowDepth.glsl{@}#!ATTRIBUTES

#!UNIFORMS

#!VARYINGS

#!SHADER: ShadowDepth.vs
void main() {
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: ShadowDepth.fs
void main() {
    gl_FragColor = vec4(vec3(gl_FragCoord.x), 1.0);
}{@}instance.vs{@}vec3 transformNormal(vec3 n, vec4 orientation) {
    vec3 nn = n + 2.0 * cross(orientation.xyz, cross(orientation.xyz, n) + orientation.w * n);
    return nn;
}

vec3 transformPosition(vec3 position, vec3 offset, vec3 scale, vec4 orientation) {
    vec3 _pos = position;
    _pos *= scale;

    _pos = _pos + 2.0 * cross(orientation.xyz, cross(orientation.xyz, _pos) + orientation.w * _pos);
    _pos += offset;
    return _pos;
}

vec3 transformPosition(vec3 position, vec3 offset, vec4 orientation) {
    vec3 _pos = position;

    _pos = _pos + 2.0 * cross(orientation.xyz, cross(orientation.xyz, _pos) + orientation.w * _pos);
    _pos += offset;
    return _pos;
}

vec3 transformPosition(vec3 position, vec3 offset, float scale, vec4 orientation) {
    return transformPosition(position, offset, vec3(scale), orientation);
}

vec3 transformPosition(vec3 position, vec3 offset) {
    return position + offset;
}

vec3 transformPosition(vec3 position, vec3 offset, float scale) {
    vec3 pos = position * scale;
    return pos + offset;
}

vec3 transformPosition(vec3 position, vec3 offset, vec3 scale) {
    vec3 pos = position * scale;
    return pos + offset;
}{@}lights.fs{@}vec3 worldLight(vec3 pos, vec3 vpos) {
    vec4 mvPos = modelViewMatrix * vec4(vpos, 1.0);
    vec4 worldPosition = viewMatrix * vec4(pos, 1.0);
    return worldPosition.xyz - mvPos.xyz;
}{@}lights.vs{@}vec3 worldLight(vec3 pos) {
    vec4 mvPos = modelViewMatrix * vec4(position, 1.0);
    vec4 worldPosition = viewMatrix * vec4(pos, 1.0);
    return worldPosition.xyz - mvPos.xyz;
}

vec3 worldLight(vec3 lightPos, vec3 localPos) {
    vec4 mvPos = modelViewMatrix * vec4(localPos, 1.0);
    vec4 worldPosition = viewMatrix * vec4(lightPos, 1.0);
    return worldPosition.xyz - mvPos.xyz;
}{@}shadows.fs{@}float shadowCompare(sampler2D map, vec2 coords, float compare) {
    return step(compare, texture2D(map, coords).r);
}

float shadowLerp(sampler2D map, vec2 coords, float compare, float size) {
    const vec2 offset = vec2(0.0, 1.0);

    vec2 texelSize = vec2(1.0) / size;
    vec2 centroidUV = floor(coords * size + 0.5) / size;

    float lb = shadowCompare(map, centroidUV + texelSize * offset.xx, compare);
    float lt = shadowCompare(map, centroidUV + texelSize * offset.xy, compare);
    float rb = shadowCompare(map, centroidUV + texelSize * offset.yx, compare);
    float rt = shadowCompare(map, centroidUV + texelSize * offset.yy, compare);

    vec2 f = fract( coords * size + 0.5 );

    float a = mix( lb, lt, f.y );
    float b = mix( rb, rt, f.y );
    float c = mix( a, b, f.x );

    return c;
}

float srange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) {
    float oldRange = oldMax - oldMin;
    float newRange = newMax - newMin;
    return (((oldValue - oldMin) * newRange) / oldRange) + newMin;
}

float shadowrandom(vec3 vin) {
    vec3 v = vin * 0.1;
    float t = v.z * 0.3;
    v.y *= 0.8;
    float noise = 0.0;
    float s = 0.5;
    noise += srange(sin(v.x * 0.9 / s + t * 10.0) + sin(v.x * 2.4 / s + t * 15.0) + sin(v.x * -3.5 / s + t * 4.0) + sin(v.x * -2.5 / s + t * 7.1), -1.0, 1.0, -0.3, 0.3);
    noise += srange(sin(v.y * -0.3 / s + t * 18.0) + sin(v.y * 1.6 / s + t * 18.0) + sin(v.y * 2.6 / s + t * 8.0) + sin(v.y * -2.6 / s + t * 4.5), -1.0, 1.0, -0.3, 0.3);
    return noise;
}

float shadowLookup(sampler2D map, vec3 coords, float size, float compare, vec3 wpos) {
    float shadow = 1.0;

    #if defined(SHADOW_MAPS)
    bool frustumTest = coords.x >= 0.0 && coords.x <= 1.0 && coords.y >= 0.0 && coords.y <= 1.0 && coords.z <= 1.0;
    if (frustumTest) {
        vec2 texelSize = vec2(1.0) / size;

        float dx0 = -texelSize.x;
        float dy0 = -texelSize.y;
        float dx1 = +texelSize.x;
        float dy1 = +texelSize.y;

        float rnoise = shadowrandom(wpos) * 0.00015;
        dx0 += rnoise;
        dy0 -= rnoise;
        dx1 += rnoise;
        dy1 -= rnoise;

        #if defined(SHADOWS_MED)
        shadow += shadowCompare(map, coords.xy + vec2(0.0, dy0), compare);
        //        shadow += shadowCompare(map, coords.xy + vec2(dx1, dy0), compare);
        shadow += shadowCompare(map, coords.xy + vec2(dx0, 0.0), compare);
        shadow += shadowCompare(map, coords.xy, compare);
        shadow += shadowCompare(map, coords.xy + vec2(dx1, 0.0), compare);
        //        shadow += shadowCompare(map, coords.xy + vec2(dx0, dy1), compare);
        shadow += shadowCompare(map, coords.xy + vec2(0.0, dy1), compare);
        shadow /= 5.0;

        #elif defined(SHADOWS_HIGH)
        shadow = shadowLerp(map, coords.xy + vec2(dx0, dy0), compare, size);
        shadow += shadowLerp(map, coords.xy + vec2(0.0, dy0), compare, size);
        shadow += shadowLerp(map, coords.xy + vec2(dx1, dy0), compare, size);
        shadow += shadowLerp(map, coords.xy + vec2(dx0, 0.0), compare, size);
        shadow += shadowLerp(map, coords.xy, compare, size);
        shadow += shadowLerp(map, coords.xy + vec2(dx1, 0.0), compare, size);
        shadow += shadowLerp(map, coords.xy + vec2(dx0, dy1), compare, size);
        shadow += shadowLerp(map, coords.xy + vec2(0.0, dy1), compare, size);
        shadow += shadowLerp(map, coords.xy + vec2(dx1, dy1), compare, size);
        shadow /= 9.0;

        #else
        shadow = shadowCompare(map, coords.xy, compare);
        #endif
    }

        #endif

    return clamp(shadow, 0.0, 1.0);
}

#test !!window.Metal
vec3 transformShadowLight(vec3 pos, vec3 vpos, mat4 mvMatrix, mat4 viewMatrix) {
    vec4 mvPos = mvMatrix * vec4(vpos, 1.0);
    vec4 worldPosition = viewMatrix * vec4(pos, 1.0);
    return normalize(worldPosition.xyz - mvPos.xyz);
}

float getShadow(vec3 pos, vec3 normal, float bias, Uniforms uniforms, GlobalUniforms globalUniforms, sampler2D shadowMap) {
    float shadow = 1.0;
    #if defined(SHADOW_MAPS)

    vec4 shadowMapCoords;
    vec3 coords;
    float lookup;

    for (int i = 0; i < SHADOW_COUNT; i++) {
        shadowMapCoords = uniforms.shadowMatrix[i] * vec4(pos, 1.0);
        coords = (shadowMapCoords.xyz / shadowMapCoords.w) * vec3(0.5) + vec3(0.5);

        lookup = shadowLookup(shadowMap, coords, uniforms.shadowSize[i], coords.z - bias, pos);
        lookup += mix(1.0 - step(0.002, dot(transformShadowLight(uniforms.shadowLightPos[i], pos, uniforms.modelViewMatrix, globalUniforms.viewMatrix), normal)), 0.0, step(999.0, normal.x));
        shadow *= clamp(lookup, 0.0, 1.0);
    }

    #endif
    return shadow;
}

float getShadow(vec3 pos, vec3 normal, Uniforms uniforms, GlobalUniforms globalUniforms, sampler2D shadowMap) {
    return getShadow(pos, normal, 0.0, uniforms, globalUniforms, shadowMap);
}

float getShadow(vec3 pos, float bias, Uniforms uniforms, GlobalUniforms globalUniforms, sampler2D shadowMap) {
    return getShadow(pos, vec3(99999.0), bias, uniforms, globalUniforms, shadowMap);
}

float getShadow(vec3 pos, Uniforms uniforms, GlobalUniforms globalUniforms, sampler2D shadowMap) {
    return getShadow(pos, vec3(99999.0), 0.0, uniforms, globalUniforms, shadowMap);
}

float getShadow(vec3 pos, vec3 normal) {
    return 1.0;
}

float getShadow(vec3 pos, float bias) {
    return 1.0;
}

float getShadow(vec3 pos) {
    return 1.0;
}
#endtest

#test !window.Metal
vec3 transformShadowLight(vec3 pos, vec3 vpos) {
    vec4 mvPos = modelViewMatrix * vec4(vpos, 1.0);
    vec4 worldPosition = viewMatrix * vec4(pos, 1.0);
    return normalize(worldPosition.xyz - mvPos.xyz);
}

float getShadow(vec3 pos, vec3 normal, float bias) {
    float shadow = 1.0;
    #if defined(SHADOW_MAPS)

    vec4 shadowMapCoords;
    vec3 coords;
    float lookup;

    #pragma unroll_loop
    for (int i = 0; i < SHADOW_COUNT; i++) {
        shadowMapCoords = shadowMatrix[i] * vec4(pos, 1.0);
        coords = (shadowMapCoords.xyz / shadowMapCoords.w) * vec3(0.5) + vec3(0.5);

        lookup = shadowLookup(shadowMap[i], coords, shadowSize[i], coords.z - bias, pos);
        lookup += mix(1.0 - step(0.002, dot(transformShadowLight(shadowLightPos[i], pos), normal)), 0.0, step(999.0, normal.x));
        shadow *= clamp(lookup, 0.0, 1.0);
    }

    #endif
    return shadow;
}

float getShadow(vec3 pos, vec3 normal) {
    return getShadow(pos, normal, 0.0);
}

float getShadow(vec3 pos, float bias) {
    return getShadow(pos, vec3(99999.0), bias);
}

float getShadow(vec3 pos) {
    return getShadow(pos, vec3(99999.0), 0.0);
}
#endtest{@}fresnel.glsl{@}float getFresnel(vec3 normal, vec3 viewDir, float power) {
    float d = dot(normalize(normal), normalize(viewDir));
    return 1.0 - pow(abs(d), power);
}

//viewDir = -vec3(modelViewMatrix * vec4(position, 1.0));{@}FXAA.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMask;

#!VARYINGS
varying vec2 v_rgbNW;
varying vec2 v_rgbNE;
varying vec2 v_rgbSW;
varying vec2 v_rgbSE;
varying vec2 v_rgbM;

#!SHADER: FXAA.vs

varying vec2 vUv;

void main() {
    vUv = uv;

    vec2 fragCoord = uv * resolution;
    vec2 inverseVP = 1.0 / resolution.xy;
    v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;
    v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;
    v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;
    v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;
    v_rgbM = vec2(fragCoord * inverseVP);

    gl_Position = vec4(position, 1.0);
}

#!SHADER: FXAA.fs

#require(conditionals.glsl)

#ifndef FXAA_REDUCE_MIN
    #define FXAA_REDUCE_MIN   (1.0/ 128.0)
#endif
#ifndef FXAA_REDUCE_MUL
    #define FXAA_REDUCE_MUL   (1.0 / 8.0)
#endif
#ifndef FXAA_SPAN_MAX
    #define FXAA_SPAN_MAX     8.0
#endif

vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution,
            vec2 v_rgbNW, vec2 v_rgbNE,
            vec2 v_rgbSW, vec2 v_rgbSE,
            vec2 v_rgbM) {
    vec4 color;
    mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);
    vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;
    vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;
    vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;
    vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;
    vec4 texColor = texture2D(tex, v_rgbM);
    vec3 rgbM  = texColor.xyz;
    vec3 luma = vec3(0.299, 0.587, 0.114);
    float lumaNW = dot(rgbNW, luma);
    float lumaNE = dot(rgbNE, luma);
    float lumaSW = dot(rgbSW, luma);
    float lumaSE = dot(rgbSE, luma);
    float lumaM  = dot(rgbM,  luma);
    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));

    mediump vec2 dir;
    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));

    float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
                          (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);

    float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
    dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
              max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
              dir * rcpDirMin)) * inverseVP;

    vec3 rgbA = 0.5 * (
        texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
        texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
    vec3 rgbB = rgbA * 0.5 + 0.25 * (
        texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +
        texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);

    float lumaB = dot(rgbB, luma);

    color = vec4(rgbB, texColor.a);
    color = mix(color, vec4(rgbA, texColor.a), when_lt(lumaB, lumaMin));
    color = mix(color, vec4(rgbA, texColor.a), when_gt(lumaB, lumaMax));

    return color;
}

void main() {
    vec2 fragCoord = vUv * resolution;
    float mask = texture2D(tMask, vUv).r;
    if (mask < 0.5) {
        gl_FragColor = fxaa(tDiffuse, fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);
    } else {
        gl_FragColor = texture2D(tDiffuse, vUv);
    }
    gl_FragColor.a = 1.0;
}
{@}gaussianblur.fs{@}vec4 blur13(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
  vec4 color = vec4(0.0);
  vec2 off1 = vec2(1.411764705882353) * direction;
  vec2 off2 = vec2(3.2941176470588234) * direction;
  vec2 off3 = vec2(5.176470588235294) * direction;
  color += texture2D(image, uv) * 0.1964825501511404;
  color += texture2D(image, uv + (off1 / resolution)) * 0.2969069646728344;
  color += texture2D(image, uv - (off1 / resolution)) * 0.2969069646728344;
  color += texture2D(image, uv + (off2 / resolution)) * 0.09447039785044732;
  color += texture2D(image, uv - (off2 / resolution)) * 0.09447039785044732;
  color += texture2D(image, uv + (off3 / resolution)) * 0.010381362401148057;
  color += texture2D(image, uv - (off3 / resolution)) * 0.010381362401148057;
  return color;
}

vec4 blur5(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
  vec4 color = vec4(0.0);
  vec2 off1 = vec2(1.3333333333333333) * direction;
  color += texture2D(image, uv) * 0.29411764705882354;
  color += texture2D(image, uv + (off1 / resolution)) * 0.35294117647058826;
  color += texture2D(image, uv - (off1 / resolution)) * 0.35294117647058826;
  return color;
}

vec4 blur9(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
  vec4 color = vec4(0.0);
  vec2 off1 = vec2(1.3846153846) * direction;
  vec2 off2 = vec2(3.2307692308) * direction;
  color += texture2D(image, uv) * 0.2270270270;
  color += texture2D(image, uv + (off1 / resolution)) * 0.3162162162;
  color += texture2D(image, uv - (off1 / resolution)) * 0.3162162162;
  color += texture2D(image, uv + (off2 / resolution)) * 0.0702702703;
  color += texture2D(image, uv - (off2 / resolution)) * 0.0702702703;
  return color;
}

vec4 gaussianblur(sampler2D image, vec2 uv, float steps, vec2 resolution, vec2 direction) {

  vec4 blend = vec4(0.);
  float sum = 1.;
  float m = 1.;
  float n = steps;

  for (float i = 0.; i < 100.; i += 1.) {
      if(i >= 2. * steps) break;
      float k = i;
      float j = i - 0.5 * steps;
      blend += m * texture(image, uv + j * direction / resolution);
      m *= (n - k) / (k + 1.);
      sum += m;
  } 

  return blend / sum;

}{@}glscreenprojection.glsl{@}vec2 frag_coord(vec4 glPos) {
    return ((glPos.xyz / glPos.w) * 0.5 + 0.5).xy;
}

vec2 getProjection(vec3 pos, mat4 projMatrix) {
    vec4 mvpPos = projMatrix * vec4(pos, 1.0);
    return frag_coord(mvpPos);
}

void applyNormal(inout vec3 pos, mat4 projNormalMatrix) {
    vec3 transformed = vec3(projNormalMatrix * vec4(pos, 0.0));
    pos = transformed;
}{@}DefaultText.glsl{@}#!ATTRIBUTES

#!UNIFORMS

uniform sampler2D tMap;
uniform vec3 uColor;
uniform float uAlpha;

#!VARYINGS

varying vec2 vUv;

#!SHADER: DefaultText.vs

void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: DefaultText.fs

#require(msdf.glsl)

void main() {
    float alpha = msdf(tMap, vUv);

    gl_FragColor.rgb = uColor;
    gl_FragColor.a = alpha * uAlpha;
}
{@}msdf.glsl{@}float msdf(vec3 tex, vec2 uv) {
    // TODO: fallback for fwidth for webgl1 (need to enable ext)
    float signedDist = max(min(tex.r, tex.g), min(max(tex.r, tex.g), tex.b)) - 0.5;
    float d = fwidth(signedDist);
    float alpha = smoothstep(-d, d, signedDist);
    if (alpha < 0.01) discard;
    return alpha;
}

float msdf(sampler2D tMap, vec2 uv) {
    vec3 tex = texture2D(tMap, uv).rgb;
    return msdf( tex, uv );
}

float strokemsdf(sampler2D tMap, vec2 uv, float stroke, float padding) {
    vec3 tex = texture2D(tMap, uv).rgb;
    float signedDist = max(min(tex.r, tex.g), min(max(tex.r, tex.g), tex.b)) - 0.5;
    float t = stroke;
    float alpha = smoothstep(-t, -t + padding, signedDist) * smoothstep(t, t - padding, signedDist);
    return alpha;
}{@}GLUIBatch.glsl{@}#!ATTRIBUTES
attribute vec3 offset;
attribute vec2 scale;
attribute float rotation;
//attributes

#!UNIFORMS
uniform sampler2D tMap;
uniform vec3 uColor;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;
//varyings

#!SHADER: Vertex

mat4 rotationMatrix(vec3 axis, float angle) {
    axis = normalize(axis);
    float s = sin(angle);
    float c = cos(angle);
    float oc = 1.0 - c;

    return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,
    oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,
    oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,
    0.0,                                0.0,                                0.0,                                1.0);
}

void main() {
    vUv = uv;
    //vdefines

    vec3 pos = vec3(rotationMatrix(vec3(0.0, 0.0, 1.0), rotation) * vec4(position, 1.0));
    pos.xy *= scale;
    pos.xyz += offset;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment
void main() {
    gl_FragColor = vec4(1.0);
}{@}GLUIBatchText.glsl{@}#!ATTRIBUTES
attribute vec3 offset;
attribute vec2 scale;
attribute float rotation;
//attributes

#!UNIFORMS
uniform sampler2D tMap;
uniform vec3 uColor;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;
//varyings

#!SHADER: Vertex

mat4 lrotationMatrix(vec3 axis, float angle) {
    axis = normalize(axis);
    float s = sin(angle);
    float c = cos(angle);
    float oc = 1.0 - c;

    return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,
    oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,
    oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,
    0.0,                                0.0,                                0.0,                                1.0);
}

void main() {
    vUv = uv;
    //vdefines

    vec3 pos = vec3(lrotationMatrix(vec3(0.0, 0.0, 1.0), rotation) * vec4(position, 1.0));

    //custommain

    pos.xy *= scale;
    pos += offset;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(msdf.glsl)

void main() {
    float alpha = msdf(tMap, vUv);

    gl_FragColor.rgb = v_uColor;
    gl_FragColor.a = alpha * v_uAlpha;
}
{@}GLUIColor.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;

#!SHADER: GLUIColor.vs
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: GLUIColor.fs
void main() {
    vec2 uv = vUv;
    vec3 uvColor = vec3(uv, 1.0);
    gl_FragColor = vec4(mix(uColor, uvColor, 0.0), uAlpha);
}{@}GLUIObject.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;

#!SHADER: GLUIObject.vs
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: GLUIObject.fs
void main() {
    gl_FragColor = texture2D(tMap, vUv);
    gl_FragColor.a *= uAlpha;
}{@}gluimask.fs{@}uniform vec4 uMaskValues;

#require(range.glsl)

vec2 getMaskUV() {
    vec2 ores = gl_FragCoord.xy / resolution;
    vec2 uv;
    uv.x = range(ores.x, uMaskValues.x, uMaskValues.z, 0.0, 1.0);
    uv.y = 1.0 - range(1.0 - ores.y, uMaskValues.y, uMaskValues.w, 0.0, 1.0);
    return uv;
}{@}luma.fs{@}float luma(vec3 color) {
  return dot(color, vec3(0.299, 0.587, 0.114));
}

float luma(vec4 color) {
  return dot(color.rgb, vec3(0.299, 0.587, 0.114));
}{@}normalmap.glsl{@}vec3 unpackNormal( vec3 eye_pos, vec3 surf_norm, sampler2D normal_map, float intensity, float scale, vec2 uv ) {
    surf_norm = normalize(surf_norm);
    
    vec3 q0 = dFdx( eye_pos.xyz );
    vec3 q1 = dFdy( eye_pos.xyz );
    vec2 st0 = dFdx( uv.st );
    vec2 st1 = dFdy( uv.st );
    
    vec3 S = normalize( q0 * st1.t - q1 * st0.t );
    vec3 T = normalize( -q0 * st1.s + q1 * st0.s );
    vec3 N = normalize( surf_norm );
    
    vec3 mapN = texture2D( normal_map, uv * scale ).xyz * 2.0 - 1.0;
    mapN.xy *= intensity;
    mat3 tsn = mat3( S, T, N );
    return normalize( tsn * mapN );
}

//mvPosition.xyz, normalMatrix * normal, normalMap, intensity, scale, uv{@}phong.fs{@}#define saturate(a) clamp( a, 0.0, 1.0 )

float dPhong(float shininess, float dotNH) {
    return (shininess * 0.5 + 1.0) * pow(dotNH, shininess);
}

vec3 schlick(vec3 specularColor, float dotLH) {
    float fresnel = exp2((-5.55437 * dotLH - 6.98316) * dotLH);
    return (1.0 - specularColor) * fresnel + specularColor;
}

vec3 calcBlinnPhong(vec3 specularColor, float shininess, vec3 normal, vec3 lightDir, vec3 viewDir) {
    vec3 halfDir = normalize(lightDir + viewDir);
    
    float dotNH = saturate(dot(normal, halfDir));
    float dotLH = saturate(dot(lightDir, halfDir));

    vec3 F = schlick(specularColor, dotLH);
    float G = 0.85;
    float D = dPhong(shininess, dotNH);
    
    return F * G * D;
}

vec3 calcBlinnPhong(vec3 specularColor, float shininess, vec3 normal, vec3 lightDir, vec3 viewDir, float minTreshold) {
    vec3 halfDir = normalize(lightDir + viewDir);

    float dotNH = saturate(dot(normal, halfDir));
    float dotLH = saturate(dot(lightDir, halfDir));

    dotNH = range(dotNH, 0.0, 1.0, minTreshold, 1.0);
    dotLH = range(dotLH, 0.0, 1.0, minTreshold, 1.0);

    vec3 F = schlick(specularColor, dotLH);
    float G = 0.85;
    float D = dPhong(shininess, dotNH);

    return F * G * D;
}

vec3 phong(float amount, vec3 diffuse, vec3 specular, float shininess, float attenuation, vec3 normal, vec3 lightDir, vec3 viewDir) {
    float cosineTerm = saturate(dot(normal, lightDir));
    vec3 brdf = calcBlinnPhong(specular, shininess, normal, lightDir, viewDir);
    return brdf * amount * diffuse * attenuation * cosineTerm;
}

vec3 phong(float amount, vec3 diffuse, vec3 specular, float shininess, float attenuation, vec3 normal, vec3 lightDir, vec3 viewDir, float minThreshold) {
    float cosineTerm = saturate(range(dot(normal, lightDir), 0.0, 1.0, minThreshold, 1.0));
    vec3 brdf = calcBlinnPhong(specular, shininess, normal, lightDir, viewDir, minThreshold);
    return brdf * amount * diffuse * attenuation * cosineTerm;
}

//viewDir = -mvPosition.xyz
//lightDir = normalize(lightPos){@}radialblur.fs{@}vec3 radialBlur( sampler2D map, vec2 uv, float size, vec2 resolution, float quality ) {
    vec3 color = vec3(0.);

    const float pi2 = 3.141596 * 2.0;
    const float direction = 8.0;

    vec2 radius = size / resolution;
    float test = 1.0;

    for ( float d = 0.0; d < pi2 ; d += pi2 / direction ) {
        vec2 t = radius * vec2( cos(d), sin(d));
        for ( float i = 1.0; i <= 100.0; i += 1.0 ) {
            if (i >= quality) break;
            color += texture2D( map, uv + t * i / quality ).rgb ;
        }
    }

    return color / ( quality * direction);
}{@}range.glsl{@}

float range(float oldValue, float oldMin, float oldMax, float newMin, float newMax) {
    vec3 sub = vec3(oldValue, newMax, oldMax) - vec3(oldMin, newMin, oldMin);
    return sub.x * sub.y / sub.z + newMin;
}

vec2 range(vec2 oldValue, vec2 oldMin, vec2 oldMax, vec2 newMin, vec2 newMax) {
    vec2 oldRange = oldMax - oldMin;
    vec2 newRange = newMax - newMin;
    vec2 val = oldValue - oldMin;
    return val * newRange / oldRange + newMin;
}

vec3 range(vec3 oldValue, vec3 oldMin, vec3 oldMax, vec3 newMin, vec3 newMax) {
    vec3 oldRange = oldMax - oldMin;
    vec3 newRange = newMax - newMin;
    vec3 val = oldValue - oldMin;
    return val * newRange / oldRange + newMin;
}

float crange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) {
    return clamp(range(oldValue, oldMin, oldMax, newMin, newMax), min(newMin, newMax), max(newMin, newMax));
}

vec2 crange(vec2 oldValue, vec2 oldMin, vec2 oldMax, vec2 newMin, vec2 newMax) {
    return clamp(range(oldValue, oldMin, oldMax, newMin, newMax), min(newMin, newMax), max(newMin, newMax));
}

vec3 crange(vec3 oldValue, vec3 oldMin, vec3 oldMax, vec3 newMin, vec3 newMax) {
    return clamp(range(oldValue, oldMin, oldMax, newMin, newMax), min(newMin, newMax), max(newMin, newMax));
}

float rangeTransition(float t, float x, float padding) {
    float transition = crange(t, 0.0, 1.0, -padding, 1.0 + padding);
    return crange(x, transition - padding, transition + padding, 1.0, 0.0);
}
{@}refl.fs{@}vec3 reflection(vec3 worldPosition, vec3 normal) {
    vec3 cameraToVertex = normalize(worldPosition - cameraPosition);
    
    return reflect(cameraToVertex, normal);
}

vec3 refraction(vec3 worldPosition, vec3 normal, float rRatio) {
    vec3 cameraToVertex = normalize(worldPosition - cameraPosition);
    
    return refract(cameraToVertex, normal, rRatio);
}

vec4 envColor(samplerCube map, vec3 vec) {
    float flipNormal = 1.0;
    return textureCube(map, flipNormal * vec3(-1.0 * vec.x, vec.yz));
}

vec4 envColorEqui(sampler2D map, vec3 direction) {
    vec2 uv;
    uv.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * 0.31830988618 + 0.5;
    uv.x = atan( direction.z, direction.x ) * 0.15915494 + 0.5;
    return texture2D(map, uv);
}{@}refl.vs{@}vec3 inverseTransformDirection(in vec3 normal, in mat4 matrix) {
    return normalize((matrix * vec4(normal, 0.0) * matrix).xyz);
}

vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
    return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
}

vec3 reflection(vec4 worldPosition, vec3 normal) {
    vec3 transformedNormal = normalMatrix * normal;
    vec3 cameraToVertex = normalize(worldPosition.xyz - cameraPosition);
    vec3 worldNormal = inverseTransformDirection(transformedNormal, viewMatrix);

    return reflect(cameraToVertex, worldNormal);
}

vec3 reflection(vec4 worldPosition) {
    return reflection(worldPosition, normalMatrix * normal);
}

vec3 refraction(vec4 worldPosition, vec3 normal, float refractionRatio) {
    vec3 transformedNormal = normal;
    vec3 cameraToVertex = normalize(worldPosition.xyz - cameraPosition);
    vec3 worldNormal = inverseTransformDirection(transformedNormal, viewMatrix);

    return refract(cameraToVertex, worldNormal, refractionRatio);
}

vec3 refraction(vec4 worldPosition, float refractionRatio) {
    return refraction(worldPosition, normalMatrix * normal, refractionRatio);
}{@}rgb2hsv.fs{@}vec3 rgb2hsv(vec3 c) {
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
    
    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv2rgb(vec3 c) {
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}{@}rgbshift.fs{@}vec4 getRGB(sampler2D tDiffuse, vec2 uv, float angle, float amount) {
    vec2 offset = vec2(cos(angle), sin(angle)) * amount;
    vec4 r = texture2D(tDiffuse, uv + offset);
    vec4 g = texture2D(tDiffuse, uv);
    vec4 b = texture2D(tDiffuse, uv - offset);
    return vec4(r.r, g.g, b.b, g.a);
}{@}rotation.glsl{@}mat4 rotationMatrix(vec3 axis, float angle) {
    axis = normalize(axis);
    float s = sin(angle);
    float c = cos(angle);
    float oc = 1.0 - c;

    return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,
                oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,
                oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,
                0.0,                                0.0,                                0.0,                                1.0);
}


mat2 rotationMatrix(float angle) {
  float s = sin(angle);
  float c = cos(angle);
  return mat2(c, -s, s, c);
}{@}simplenoise.glsl{@}float getNoise(vec2 uv, float time) {
    float x = uv.x * uv.y * time * 1000.0;
    x = mod(x, 13.0) * mod(x, 123.0);
    float dx = mod(x, 0.01);
    float amount = clamp(0.1 + dx * 100.0, 0.0, 1.0);
    return amount;
}

#test Device.mobile
float sinf(float x) {
    x*=0.159155;
    x-=floor(x);
    float xx=x*x;
    float y=-6.87897;
    y=y*xx+33.7755;
    y=y*xx-72.5257;
    y=y*xx+80.5874;
    y=y*xx-41.2408;
    y=y*xx+6.28077;
    return x*y;
}
#endtest

#test !Device.mobile
    #define sinf sin
#endtest

highp float getRandom(vec2 co) {
    highp float a = 12.9898;
    highp float b = 78.233;
    highp float c = 43758.5453;
    highp float dt = dot(co.xy, vec2(a, b));
    highp float sn = mod(dt, 3.14);
    return fract(sin(sn) * c);
}

float cnoise(vec3 v) {
    float t = v.z * 0.3;
    v.y *= 0.8;
    float noise = 0.0;
    float s = 0.5;
    noise += (sinf(v.x * 0.9 / s + t * 10.0) + sinf(v.x * 2.4 / s + t * 15.0) + sinf(v.x * -3.5 / s + t * 4.0) + sinf(v.x * -2.5 / s + t * 7.1)) * 0.3;
    noise += (sinf(v.y * -0.3 / s + t * 18.0) + sinf(v.y * 1.6 / s + t * 18.0) + sinf(v.y * 2.6 / s + t * 8.0) + sinf(v.y * -2.6 / s + t * 4.5)) * 0.3;
    return noise;
}

float cnoise(vec2 v) {
    float t = v.x * 0.3;
    v.y *= 0.8;
    float noise = 0.0;
    float s = 0.5;
    noise += (sinf(v.x * 0.9 / s + t * 10.0) + sinf(v.x * 2.4 / s + t * 15.0) + sinf(v.x * -3.5 / s + t * 4.0) + sinf(v.x * -2.5 / s + t * 7.1)) * 0.3;
    noise += (sinf(v.y * -0.3 / s + t * 18.0) + sinf(v.y * 1.6 / s + t * 18.0) + sinf(v.y * 2.6 / s + t * 8.0) + sinf(v.y * -2.6 / s + t * 4.5)) * 0.3;
    return noise;
}{@}transformUV.glsl{@}vec2 translateUV(vec2 uv, vec2 translate) {
    return uv - translate;
}

vec2 rotateUV(vec2 uv, float r, vec2 origin) {
    float c = cos(r);
    float s = sin(r);
    mat2 m = mat2(c, -s, 
                  s, c);
    vec2 st = uv - origin;
    st = m * st;
    return st + origin;
}

vec2 scaleUV(vec2 uv, vec2 scale, vec2 origin) {
    vec2 st = uv - origin;
    st /= scale;
    return st + origin;
}

vec2 rotateUV(vec2 uv, float r) {
    return rotateUV(uv, r, vec2(0.5));
}

vec2 scaleUV(vec2 uv, vec2 scale) {
    return scaleUV(uv, scale, vec2(0.5));
}

vec2 transformUV(vec2 uv, float a[9]) {

    // Array consists of the following
    // 0 translate.x
    // 1 translate.y
    // 2 skew.x
    // 3 skew.y
    // 4 rotate
    // 5 scale.x
    // 6 scale.y
    // 7 origin.x
    // 8 origin.y

    vec2 st = uv;
    
    //Translate
    st -= vec2(a[0], a[1]);

    //Skew
    st = st + st.gr * vec2(a[2], a[3]);

    //Rotate
    st = rotateUV(st, a[4], vec2(a[7], a[8]));

    //Scale
    st = scaleUV(st, vec2(a[5], a[6]), vec2(a[7], a[8]));

    return st;
}{@}CustomGLText.glsl{@}#!ATTRIBUTES
attribute float weight;

#!UNIFORMS

uniform sampler2D tMap;
uniform sampler2D tMapBold;
uniform vec3 uColor;
uniform vec3 uColorBold;
uniform float uAlpha;

#!VARYINGS

varying vec2 vUv;
varying float vWeight;

#!SHADER: Vertex

void main() {
    vUv = uv;
    vWeight = weight;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment
#require(msdf.glsl)
void main() {
    vec3 texRegular = texture2D(tMap, vUv).rgb;
    vec3 texBold = texture2D(tMapBold, vUv).rgb;

    vec3 tex = mix( texRegular, texBold, vWeight );
    vec3 color = mix( uColor, uColorBold, vWeight );

    float alpha = msdf( tex, vUv );

    gl_FragColor.rgb = color;
    gl_FragColor.a = alpha * uAlpha;
}{@}SceneBasicShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform sampler2D tMapTo;
uniform float uFade;

#!VARYINGS
varying vec2 vUv;

#!SHADER: SceneBasicShader.vs
void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}

#!SHADER: SceneBasicShader.fs
void main() {
    vec4 texel = texture2D(tMap, vUv);
    vec4 texelTo = texture2D(tMapTo, vUv);
    gl_FragColor = mix(texel, texelTo, uFade);
    gl_FragColor.a = 1.0;
}{@}LevelVFX.fs{@}uniform float uBloomAdd;
uniform float uRGBStrength;
uniform float uVignette;
uniform float uRippleTransition;
uniform float uNoise;
uniform float uVisible;
uniform float uProgress;
uniform float uProgress2;
uniform float uHit;
uniform vec3 uHitColor;
uniform sampler2D tDepth;
uniform float uScan;
uniform vec3 uScanColor;
uniform vec2 uDepthLimits;

#require(UnrealBloom.fs)
#require(rgbshift.fs)
#require(eases.glsl)
#require(range.glsl)
#require(simplenoise.glsl)
#require(transformUV.glsl)
#require(blendmodes.glsl)
#require(mousefluid.fs)
#require(depthvalue.fs)

float grid(vec2 st, float res, float width) {
  vec2 grid = fract(st*res);
  return (step(width,grid.x) * step(width*(resolution.x/resolution.y),grid.y));
}

void main() {
    vec3 color;

    vec2 uv = vUv;
    vec2 squareUV = scaleUV(vUv, vec2(1.0, resolution.x/resolution.y));

    float center = length(squareUV-0.5);
    float rippleTransition =  mix(uHit, uRippleTransition, smoothstep(0.0, 0.2, uRippleTransition));
    float transition = (1.0-rippleTransition) * 0.7;
    float ripple = smoothstep(transition-0.2, transition, center) * smoothstep(transition+0.2, transition, center);
    ripple *= smoothstep(-0.3, 0.5, rippleTransition) * smoothstep(1.1, 0.4, rippleTransition);
    //ripple += cnoise(uv*5.0+time*0.5)*0.2;
    ripple = pow(ripple, 2.0);
    ripple *= mix(0.4, 0.1, smoothstep(0.05, 0.1, uHit));

    uv = scaleUV(uv, vec2(1.0+ripple*0.5));

    float fluidMask = 0.0;
    float fluidOutline = 0.0;
    vec2 fluid = vec2(0.0);

    #test Tests.renderFluid()
      fluidMask = texture2D(tFluidMask, vUv).r;
      fluidMask *= smoothstep(1.0, 0.9, uProgress2);
      fluidOutline = smoothstep(0.0, 0.5, fluidMask) * smoothstep(1.0, 0.5, fluidMask);
      fluid = texture2D(tFluid, vUv).xy * fluidMask;

      float maxV = 20.0;
      fluid.x = clamp(fluid.x, -maxV, maxV);
      fluid.y = clamp(fluid.y, -maxV, maxV);
    #endtest
    //uv -= fluid * 0.001 * smoothstep(0.0, 0.8, length(squareUV-0.5));

    // Ripple Effects
    color = getRGB(tDiffuse, uv, 0.03+ripple+fluidOutline*0.1, uRGBStrength * 0.001 * crange(length(squareUV-0.5), 0.0, 0.6, 0.0, 1.0) * uVisible + ripple * 0.01 * uVisible).rgb;
    color += getUnrealBloom(uv) * uBloomAdd * uVisible;
    color += ripple*0.2 * uVisible;
    color = blendOverlay(color, uHitColor, ripple*0.7 * uVisible);
    color = mix(color, blendOverlay(color, uHitColor, 2.0), uHit*smoothstep(0.1, 0.8, center)*0.3*smoothstep(0.05, 0.1, uHit) * uVisible);
    color = blendOverlay(color, vec3(1.0), (abs(fluid.x)+abs(fluid.y)) * 0.02 * smoothstep(0.2, 0.8, length(squareUV-0.5)));

    // Grid Overlay Effects
    vec2 gridUV = (gl_FragCoord.xy / resolution) * 1000.0;
    float gridOverlay = (1.0-grid(gridUV * 0.8, 0.025, 0.025))*0.25;
    gridOverlay += (1.0-grid(gridUV * 0.4, 0.025, 0.02))*0.25;
    gridOverlay += (1.0-grid(gridUV * 0.2, 0.025, 0.01))*0.25;
    gridOverlay += (1.0-grid(gridUV * 0.1, 0.025, 0.005))*0.25;

    float gridFX = gridOverlay;
    gridFX *= ripple * 2.0;
    gridFX *= smoothstep(0.1, 0.9, length(squareUV-0.5));
    color = mix(color, blendOverlay(color, vec3(1.0), 2.0), gridFX * uVisible);
    color = mix(color, blendAdd(color, vec3(1.0), 2.0), gridFX*0.1 * uVisible);
    
    // Scanning Animation
    if (uScan < 1.0) {
        float depth = getDepthValue(tDepth, vUv, uDepthLimits.x, uDepthLimits.y);
        float mid = uScan;
        float start = mix(0.2, 0.002, uProgress2);
        float end = mix(0.002, 0.2, uProgress2);
        float scan = smoothstep(mid-0.05-start, mid-0.05, depth) * smoothstep(mid+end, mid, depth);
        scan *= smoothstep(0.01, 0.05, uScan) * smoothstep(1.0, 0.7, uScan);
        color = blendOverlay(color, mix(uScanColor, vec3(1.0), 0.7 + cnoise(uv*2.0+time*0.5) * 0.3), scan * mix(3.0, 1.0, uProgress2));
        float line = smoothstep(mid-0.002, mid, depth) * smoothstep(mid+0.002, mid, depth);
        line *= smoothstep(0.01, 0.05, uScan) * smoothstep(1.0, 0.7, uScan);
        color = blendAdd(color, mix(uScanColor, vec3(1.0), 0.5 + cnoise(uv*7.0+time*0.5) * 0.3), line);
    }

    // Post Effects
    color *= mix(1.0, smoothstep(1.2, 0.2, length(squareUV-0.5)), uVignette * uVisible);
    color += crange(getNoise(vUv, 10.0), 0.0, 1.0, -1.0, 1.0)*uNoise*0.2 * uVisible;

    gl_FragColor = vec4(color, 1.0);
}{@}ScanOrbShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform float uDepth;
uniform float uOpacity;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;
varying vec3 vNormal;
varying vec4 vMvPos;
varying float vDepth;
varying vec3 vPos;

#!SHADER: ScanOrbShader.vs
void main() {
    vec3 pos = position;
    vPos = pos;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);

    vUv = uv;
    vNormal = normalMatrix * normal;
    vMvPos = modelViewMatrix * vec4(pos, 1.0);
    //vDepth = 1.0 - pos.z / uDepth;
}

#!SHADER: ScanOrbShader.fs

#require(fresnel.glsl)
#require(range.glsl)
#require(simplenoise.glsl)

void main() {
    float fresnel = getFresnel(normalize(vNormal), vMvPos.xyz, 2.0 + cnoise(vUv*8.0+time*0.8)*0.4);
    float noise = cnoise(vUv*3.0+time*0.8);

    vec3 color = uColor;
    color = mix(color, vec3(1.0), 0.4);
    color = mix(color, vec3(1.0), max(0.0, noise)*fresnel);

    float alpha = 1.0 * uOpacity;
    alpha *= fresnel;
    alpha *= 0.9 + noise*0.3;

    alpha = mix(alpha, 1.0, smoothstep(0.2, 0.05, fresnel));
    color = mix(color, mix(uColor, vec3(1.0), max(0.8, -noise)), smoothstep(0.2, 0.05, fresnel));


    alpha *= uAlpha;

    if (alpha < 0.01) discard;

    gl_FragColor.rgb = color;
    gl_FragColor.a = alpha;
}{@}BackgroundQuadShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;

#!VARYINGS
varying vec2 vUv;
varying vec3 vPos;

#!SHADER: Vertex

void main() {
    vUv = uv;
    vec3 pos = position;
    vPos = pos;
    gl_Position = vec4(pos, 1.0);
}

#!SHADER: Fragment

void main() {
    gl_FragColor = texture2D(tMap, vUv);
{@}BackgroundShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform float uProgress;
uniform vec3 uColor;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex

void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}

#!SHADER: Fragment

#require(range.glsl)
#require(transformUV.glsl)
#require(simplenoise.glsl)


void main() {
    vec2 uv = scaleUV(vUv, vec2(1.0, resolution.x/resolution.y));

    vec3 innerColor = mix(uColor*0.18, uColor*1.1, smoothstep(0.0, 0.8, uProgress));
    innerColor = mix(innerColor, vec3(1.0), smoothstep(0.8, 1.5, uProgress));
    innerColor = mix(innerColor, vec3(1.0), smoothstep(0.98, 1.02, uProgress)*0.2);

    vec3 outerColor = mix(vec3(0.0), uColor, smoothstep(0.0, 1.3, uProgress));
    vec3 color = mix(outerColor, innerColor, smoothstep(0.6, 0.0, length(uv-0.5)));

    float rings = fract(length(uv-0.5)*2.0-time*0.5);
    rings = smoothstep(0.4, 0.7, rings) * smoothstep(1.0, 0.7, rings);
    color *= 1.0 + rings*0.1;

    gl_FragColor = vec4(color, 1.0);
}{@}BlendQuadShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform sampler2D tMap;
uniform float uBlend;
uniform float uDark;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex

void main() {
    vUv = uv;
    vec3 pos = position;
    gl_Position = vec4(pos, 1.0);
}

#!SHADER: Fragment
#require(blendmodes.glsl)
#require(luma.fs)

void main() {
    vec3 tex = texture2D(tMap, vUv).rgb;

    vec3 color = mix(tex, uColor, (uBlend - uDark) * 0.6);

    if (uDark > 0.0) {
        vec3 blendColor = mix(tex, vec3(luma(tex)), uBlend);
        blendColor = blendHardLight(tex, uColor, uBlend);

        color = mix(color, blendColor, uDark);
    }

    gl_FragColor.rgb = color;
    gl_FragColor.a = 1.0;
}{@}CloudsShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMask;
uniform float uFieldOfView;
uniform vec4 orientation;
uniform vec2 uShape;
uniform vec3 uVelocity;
uniform vec3 uOffset;
uniform float uLightMultiplier;
uniform highp sampler2D noiseTexture;
uniform vec3 uBackgroundColor;
uniform vec3 uColorCloud0;
uniform vec3 uColorCloud1;
uniform vec3 uColorCloud2;
uniform vec3 uColorCloud3;
uniform float uLightBrightness;
uniform float uLightDecay;
uniform vec3 uLightColor;
uniform float uShadowIntensity;
uniform vec3 uCloudVelocity;
uniform int uSteps;
uniform float uHeight;
uniform float uProgress;
uniform float uUseLighting;
uniform float uCeiling;

uniform vec3 uLights[10];
uniform vec3 uScanLight;
uniform vec3 uBackLight;
uniform float uBackLightIntensity;

uniform vec3 uLaserColor;
uniform vec3 uScanData;
uniform float uCeiling;


#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex.vs

void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.);

}


#!SHADER: Fragment.fs
#require(transformUV.glsl)

vec3 orientate( vec4 quat, vec3 vec) {
    return  vec + 2.0 * cross( cross( vec, quat.xyz ) + quat.w * vec, quat.xyz );
}

//Fom IÃ±igo Quilez noise.
float noise( in vec3 u ) {
    vec3 x = u ;
    vec3 p = floor(x);
    vec3 f = fract(x);
  f = f*f*(3.0-2.0*f);
  vec2 uv = (p.xy+vec2(37.0,239.0)*p.z) + f.xy;
    vec2 rg = texture(noiseTexture, (uv+0.5)/256.0).yx;
  return mix( rg.x, rg.y, f.z )*2.0-1.0;

}


float map( in vec3 p, int oct ) {
  vec3 q = p  - uVelocity *time;

    float g = 0.5+0.5*noise( q*0.3 );
    
  float f;
    f  = 0.50000*noise( q ); q = q*2.02;
    if( oct>=2 ) 
    f += 0.25000*noise( q ); q = q*2.23;
    if( oct>=3 )
    f += 0.12500*noise( q ); q = q*2.41;
    if( oct>=4 )
    f += 0.06250*noise( q ); q = q*2.62;
    if( oct>=5 )
    f += 0.03125*noise( q ); 
    
    f = mix( f*uShape.x -0.75, f, g*g ) + 0.1;

    if(uCeiling > 0.5) {
        return uShape.y *f + uHeight + abs(p.y);
    } else {
        return uShape.y *f + uHeight - p.y;
    }
        
}


vec4 getColor(vec3 ro, vec3 rd, vec3 rd2, vec3 bgColor) {

    float t = 0.0;
    float t2 = 0.;
  vec4 acum = vec4(0.0);

    float steps = 0.;
    for( int i=0; i< 400; i++ ) {

       float dt = 0.02;
       float dt2 = 0.01; //This should be an uniform.

       int oct = 5 - int( log2(1.0 + t*0.5) );
       
       vec3 pos = ro + t * rd - uOffset;
       float density = map( pos, oct );

       if( density > 0.01 ) {

            vec4 color = vec4(vec3(mix(1., 1. - uShadowIntensity, density)), density);
            float mixer = clamp(density, 0.0, 1.0);
            vec3 mixColor = mix(mix(uColorCloud1, mix(uColorCloud3, uColorCloud0, smoothstep(0.8, 1.8, uProgress)), uProgress*0.2), uColorCloud2, vec3(mixer));
            color.rgb *= mixColor;           
            color.rgb = mix(color.rgb, bgColor, 1.0-exp2(-0.1*t));


            if(uUseLighting > 0.5) {

                for(int j = 0; j < 10; j ++) {

                    vec3 ll = uLights[j];

                    if(length(ll) > 0.) {
                        ll.x *= 5.;
                        ll.z += 3.;
                        vec3 lightVector = ll - pos;
                        float lightDecay = abs(dot(normalize(lightVector), vec3(0., 1., 0.)));
                        lightDecay /= pow(1. + (length(lightVector)), uLightDecay);
                        color.rgb += uLightBrightness * vec3(lightDecay) * uLightMultiplier * uLightColor;
                    }
                }

                vec3 ll = uBackLight;

                if(length(ll) > 0.) {
                    ll.x *= 5.;
                    ll.z += 3.;
                    vec3 lightVector = ll - pos;
                    float lightDecay = abs(dot(normalize(lightVector), vec3(0., 1., 0.)));
                    lightDecay /= pow(1. + (length(lightVector)), uLightDecay);
                    color.rgb += uBackLightIntensity * vec3(lightDecay) * uLightColor;
                }

                color.rgb += uScanData.y * uLaserColor / pow(1. + abs(uScanLight.z - pos.z - uScanData.x), uScanData.z);
                
            }
            color.w    = min(color.w*8.0*dt,1.0);
            color.rgb *= color.a;
            acum += color * (1.0 - acum.a);
       }

       t += dt;
       t2 += dt2;
       steps ++;
       if (acum.a > 0.99 ) break;

    }

    acum = clamp( acum, 0.0, 1.0 );

    return acum;
}

void main() {
    gl_FragColor = vec4(0.);

    if(mod(gl_FragCoord.x, 2.) == 0. || mod(gl_FragCoord.y, 2.) == 0. ) {
        discard;
        return;
    }

    vec2 xy = (2.0*gl_FragCoord.xy - resolution.xy)/resolution.y;
    vec4 conj = orientation;
    conj.xyz *= -1.;

    float z = resolution.y / tan(radians(uFieldOfView) / 2.0);
    vec3 dir =  normalize(vec3(xy, -z / resolution.y));
    dir = normalize(dir);
    dir = orientate(conj, dir);


    //This is done to evalue the fog for the orbs.
    z = resolution.y / tan(radians(30.) / 2.0);
    vec3 dir2 =  normalize(vec3(xy, -z / resolution.y));
    dir2 = normalize(dir2);
    dir2 = orientate(conj, dir2);

    vec3 eye = vec3(0.);

    vec2 uv = scaleUV(vUv, vec2(1.0, resolution.x/resolution.y));
    vec3 innerColor = mix(uBackgroundColor*0.1, uBackgroundColor, smoothstep(0.0, 1.8, uProgress));
    vec3 outerColor = mix(vec3(0.0), uBackgroundColor, smoothstep(0.5, 1.0, uProgress));
    vec3 color = mix(outerColor, innerColor, smoothstep(0.6, 0.0, length(uv-0.5)));

    gl_FragColor = getColor(eye, dir, dir2, vec3(0.));

}{@}ColorQuadShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex

void main() {
    vUv = uv;
    vec3 pos = position;
    gl_Position = vec4(pos, 1.0);
}

#!SHADER: Fragment
void main() {
    gl_FragColor.rgb = uColor;
    gl_FragColor.a = 1.0;
}{@}LightColors.glsl{@}#!ATTRIBUTES

#!UNIFORMS


#!VARYINGS


#!SHADER: Vertex


void main() {
    gl_Positiion = vec4(1.);
}

#!SHADER: Fragment
void main() {
    gl_FragColor = vec4(1.);
}{@}vfxcommon.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tBackground;
uniform vec2 uFog;
uniform float uProgress2;
uniform float uAnimate;

#!VARYINGS
varying vec3 vLightWorldPos;
varying float vFog;

#!SHADER: Vertex

#require(range.glsl)

void setupVFX(vec3 pos) {
    vLightWorldPos = vec3(modelMatrix * vec4(pos, 1.0));
    float fogMin = uFog.x;
    float fogMax = uFog.y;

    fogMin *= mix(1.0, 0.1, smoothstep(0.1, 0.05, uProgress2));
    fogMax *= mix(1.0, 0.2, smoothstep(0.1, 0.05, uProgress2));

    fogMin *= mix(1.0, 0.0, smoothstep(0.9, 1.0, uProgress2));
    fogMax *= mix(1.0, 0.7, smoothstep(0.9, 1.0, uProgress2));

    float fog1 = crange(length(cameraPosition - vLightWorldPos), fogMin, fogMin + fogMax, 0.0, 1.0);
    float fog2 = crange(length(cameraPosition - vLightWorldPos), 1.0, fogMin + fogMax, 0.0, 1.0);

    vFog = mix(fog2, fog1, uAnimate);
}

#!SHADER: Fragment

#require(range.glsl)

vec3 getLight() {
    vec3 light = vec3(0.0);
    #ifdef NUM_LIGHTS
    for (int i = 0; i < NUM_LIGHTS; i++) {
        vec3 color = lightColor[i].rgb;
        vec3 pos = lightPos[i].xyz;
        float intensity = lightProperties[i].r;
        float distance = lightProperties[i].g;

        float len = length(vLightWorldPos - pos);
        float falloff = crange(len, 0.0, distance, 1.0, 0.0);

        light += color * intensity * falloff;
    }
    #endif
    return light;
}

void applyFog(inout vec3 color) {
    vec3 bgColor = texture2D(tBackground, gl_FragCoord.xy / resolution).rgb;
    color = mix(color, bgColor, vFog);
}{@}LandingCubes.glsl{@}#!ATTRIBUTES
attribute vec3 lookup;
attribute vec4 random;

#!UNIFORMS
uniform sampler2D tPos;
uniform sampler2D tLife;
uniform sampler2D tInside;
uniform sampler2D tMatcap;
uniform float uScale;
uniform vec3 uDir;
uniform vec3 uColor0;
uniform vec3 uColor1;
uniform float uDistort;
uniform float uBlend;
uniform float uEnv;

#!VARYINGS
varying vec3 vColor;
varying vec3 vNormal;
varying vec2 vMUv;
varying float vDist;

#!SHADER: Vertex

#require(instance.vs)
#require(range.glsl)
#require(lights.vs)
#require(matcap.vs)

void main() {
    float scale = 0.5 * uScale;

    float life = texture2D(tLife, lookup.xy).x;
    scale *= smoothstep(0.0, 0.3, life) * smoothstep(1.0, 0.7, life);

    vec3 offset = texture2D(tPos, lookup.xy).xyz;
    vec3 pos = transformPosition(position, offset, scale);

    vColor = mix(uColor0, uColor1, clamp(dot(normal, normalize(worldLight(uDir))), 0.0, 1.0));
    vNormal = normal;
    vMUv = reflectMatcap(pos, modelViewMatrix, vNormal);
    vDist = length(pos - cameraPosition);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(range.glsl)
    #require(blendmodes.glsl)

void main() {
    vec2 uv = gl_FragCoord.xy / resolution;
    uv += vNormal.xy * uDistort * 0.1;

    vec3 color = texture2D(tInside, uv).rgb * 0.9;
    vec3 matcap = texture2D(tMatcap, vMUv).rgb;
    color += matcap * 0.04 * uEnv;

    //color = mix(color, vec3(0.0), crange(vDist, 35.0, 20.0, 1.0, 0.0));

    color = blendOverlay(vColor, color, uBlend);

    gl_FragColor = vec4(color, 1.0);
}{@}LandingParticles.glsl{@}#!ATTRIBUTES
attribute vec4 random;

#!UNIFORMS
uniform sampler2D tPos;
uniform sampler2D tMap;
uniform sampler2D tLife;
uniform float uSize;
uniform float DPR;
uniform float uAlpha;
uniform float uRandomStep;
uniform vec3 uColor;
uniform vec3 uColor2;

#!VARYINGS
varying float vAlpha;
varying vec3 vColor;

#!SHADER: Vertex

#require(rgb2hsv.fs)
#require(range.glsl)

void main() {
    vec4 decodedPos = texture2D(tPos, position.xy);
    vec3 pos = decodedPos.xyz;

    float life = texture2D(tLife, position.xy).x;

    vAlpha = random.y * uAlpha;
    vAlpha *= crange(life, 0.0, 0.1, 0.0, 1.0) * crange(life, 0.9, 1.0, 1.0, 0.0);
    vColor = mix(uColor, uColor2, step(random.y, uRandomStep));
    vColor = rgb2hsv(vColor);
    vColor.x += 0.03 * random.z;
    vColor = hsv2rgb(vColor);

    vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
    gl_PointSize = 0.02 * uSize * crange(random.w, 0.0, 1.0, 0.5, 3.0) * DPR * (1000.0 / length(mvPosition.xyz));
    gl_Position = projectionMatrix * mvPosition;
}

#!SHADER: Fragment
void main() {
    float mask = texture2D(tMap, gl_PointCoord.xy).r;
    gl_FragColor = vec4(vColor, mask * vAlpha);

    if (gl_FragColor.a < 0.05) discard;
}{@}LandingTubes.glsl{@}#!ATTRIBUTES
attribute vec4 random;

#!UNIFORMS
uniform sampler2D tPos;
uniform sampler2D tMatcap;
uniform sampler2D tLife;
uniform sampler2D tRandom;
uniform sampler2D tInside;
uniform vec3 uColor;
uniform float uDistortStrength;
uniform float uRandomStep;
uniform float uEnvBlend;

#!VARYINGS
varying float vSplineLife;
varying float vLength;
varying vec2 vMUv;
varying vec3 vLightWorldPos;
varying vec4 vRandom;
varying float vFog;
varying vec3 vNormal;

#!SHADER: Vertex

#require(glass.vs)
#require(matcap.vs)

void main() {
    setupGlass(pos);
    vSplineLife = texture2D(tLife, iuv).x;
    vNormal = normalize(transformedNormal);
    vMUv = reflectMatcap(pos, modelViewMatrix, vNormal);
    vRandom = texture2D(tRandom, iuv);

    vec4 worldPos = modelMatrix * vec4(pos * uReflectScale, 1.0);
    vReflect = reflection(worldPos, vNormal);
    vRefract = refraction(worldPos, vNormal, uRefractionRatio);
}

#!SHADER: Fragment

#require(range.glsl)
#require(rgb2hsv.fs)

#test !Tests.lowVaryings()
#require(glass.fs)
#endtest

#test Tests.lowVaryings()
    uniform float uEnvBlend;
#endtest

void main() {
    float a = crange(vSplineLife, 0.9, 0.99, 1.0, 0.0);
    float ta = rangeTransition(a, vLength, 0.02);

    float b = crange(vSplineLife, 0.01, 0.1, 0.0, 1.0);
    float tb = rangeTransition(b, vLength, 0.02);

    if (ta < 0.5 || tb < 0.5) discard;

    vec3 matcap = texture2D(tMatcap, vMUv).rgb;

    #test !Tests.lowVaryings()
    gFresnel = getFresnel(vNormal, vViewDir, uFresnelPow);
    #endtest

    #test Tests.lowVaryings()
    float gFresnel = 0.0;
    vec3 uFresnelColor = vec3(0.0);
    #endtest

    vec2 uv = gl_FragCoord.xy / resolution;
    uv += 0.1 * vNormal.xy * gFresnel * uDistortStrength;
    vec3 insideColor = texture2D(tInside, uv).rgb * 0.9;
    insideColor += matcap * uEnvBlend * vRandom.x;
    insideColor.rgb *= mix(vec3(1.0), uFresnelColor, gFresnel);

    vec3 highlightColor = rgb2hsv(uColor);
    highlightColor += -0.02 + vRandom.x*0.04;
    highlightColor = hsv2rgb(highlightColor);

    float highlight = step(vRandom.y, uRandomStep);
    float highlightLength = 0.5;
    float highlightPadding = 0.2;
    float highlightStrength = fract(vLength+time*0.2+vRandom.x*20.0);
    highlightStrength = smoothstep(0.5-highlightLength*(0.5+highlightPadding), 0.5-highlightLength*(0.5-highlightPadding), highlightStrength) * smoothstep(0.5+highlightLength*(0.5+highlightPadding), 0.5+highlightLength*(0.5-highlightPadding), highlightStrength);

    highlight *= highlightStrength;

    insideColor = mix(insideColor, highlightColor, highlight);
//
    insideColor = rgb2hsv(insideColor);
    insideColor.x += crange(vRandom.x, 0.0, 1.0, -1.0, 1.0)*0.01;
    insideColor = hsv2rgb(insideColor);

    gl_FragColor = vec4(insideColor, 1.0);
}{@}LandingVFX.fs{@}uniform float uBloomAdd;
uniform float uRGBStrength;
uniform float uVignette;
uniform float uNoise;
uniform float uAlpha;

#require(UnrealBloom.fs)
#require(rgbshift.fs)
#require(eases.glsl)
#require(range.glsl)
#require(simplenoise.glsl)
#require(transformUV.glsl)
#require(blendmodes.glsl)
#require(mousefluid.fs)
#require(depthvalue.fs)


void main() {
    vec3 color;

    float fluidMask = 0.0;
    float fluidOutline = 0.0;
    vec2 fluid = vec2(0.0);


    vec2 uv = vUv;
    vec2 squareUV = scaleUV(vUv, vec2(1.0, resolution.x/resolution.y));

    float center = length(squareUV-0.5);


    #test Tests.renderFluid()
    fluidMask = texture2D(tFluidMask, vUv).r;
    fluidMask *= smoothstep(0.0, 0.7, center);
    fluidOutline = smoothstep(0.0, 0.5, fluidMask) * smoothstep(1.0, 0.5, fluidMask);
    fluid = texture2D(tFluid, vUv).xy * fluidOutline;
    #endtest

//    uv += fluid * 0.00005;

    // Ripple Effects
    color = getRGB(tDiffuse, uv, 0.03, uRGBStrength * 0.0005).rgb;
    color += getUnrealBloom(uv) * uBloomAdd;

    // Post Effects
    color *= sineIn(crange(center, 0.0, 0.5, 1.0, uVignette));
    color += crange(getNoise(vUv,10.0), 0.0, 1.0, -1.0, 1.0)*uNoise*0.3;


    color=  mix(vec3(0.0), color, uAlpha);

    gl_FragColor = vec4(color, 1.0);
}{@}Level1Tubes.glsl{@}#!ATTRIBUTES
attribute vec4 random;

#!UNIFORMS
uniform sampler2D tPos;
uniform sampler2D tMatcap;
uniform sampler2D tLifeData;
uniform sampler2D tRandom;
uniform sampler2D tInside;
uniform vec3 uInsideColor;
uniform vec3 uInsideColor2;
uniform vec3 uColor;
uniform float uInsideBlend;
uniform float uDistortStrength;
uniform float uRandomStep;
uniform float uProgress;
uniform float uReflectScale;
uniform float uEnvBlend;

#!VARYINGS
varying float vSplineLife;
varying float vLength;
varying vec2 vMUv;
varying vec3 vLightWorldPos;
varying vec4 vRandom;
varying float vFog;
varying vec3 vNormal;

#!SHADER: Vertex

uniform sampler2D tBackground;
uniform vec2 uFog;
uniform float uProgress2;
uniform float uAnimate;

#test !Tests.lowVaryings()
#require(glass.vs)
#endtest

#test Tests.lowVaryings()
uniform float uReflectScale;
#endtest

#require(matcap.vs)

void main() {
    #test !Tests.lowVaryings()
    setupGlass(pos);
    #endtest

    vSplineLife = texture2D(tLifeData, iuv).z;
    vNormal = normalize(transformedNormal);
    vMUv = reflectMatcap(pos, modelViewMatrix, vNormal);
    vRandom = texture2D(tRandom, iuv);

    vec4 worldPos = modelMatrix * vec4(pos * uReflectScale, 1.0);
    #test !Tests.lowVaryings()
    vReflect = reflection(worldPos, vNormal);
    vRefract = refraction(worldPos, vNormal, uRefractionRatio);
    #endtest

    vLightWorldPos = vec3(modelMatrix * vec4(pos, 1.0));
    float fogMin = uFog.x;
    float fogMax = uFog.y;

    fogMin *= mix(1.0, 0.2, smoothstep(0.1, 0.0, uProgress2));
    fogMax *= mix(1.0, 0.7, smoothstep(0.1, 0.0, uProgress2));

    fogMin *= mix(1.0, 0.0, smoothstep(0.9, 1.0, uProgress2));
    fogMax *= mix(1.0, 0.7, smoothstep(0.9, 1.0, uProgress2));

    float fog1 = crange(length(cameraPosition - vLightWorldPos), fogMin, fogMin + fogMax, 0.0, 1.0);
    float fog2 = crange(length(cameraPosition - vLightWorldPos), 1.0, fogMin + fogMax, 0.0, 1.0);

    vFog = mix(fog2, fog1, uAnimate);
}

#!SHADER: Fragment

#require(vfxcommon.fs)
#require(rgb2hsv.fs)
#require(blendmodes.glsl)

#test !Tests.lowVaryings()
#require(glass.fs)
#endtest

#test Tests.lowVaryings()
uniform float uEnvBlend;
#endtest

void main() {
    float a = crange(vSplineLife, 0.8, 0.95, 1.0, 0.0);
    float ta = rangeTransition(a, vLength, 0.02);

    float b = crange(vSplineLife, 0.05, 0.2, 0.0, 1.0);
    float tb = rangeTransition(b, vLength, 0.02);

    if (ta < 0.5 || tb < 0.5) discard;

    vec3 matcap = texture2D(tMatcap, vMUv).rgb;

    #test !Tests.lowVaryings()
    gFresnel = getFresnel(vNormal, vViewDir, uFresnelPow);
    #endtest

    #test Tests.lowVaryings()
    float gFresnel = 0.0;
    vec3 uFresnelColor = vec3(0.0);
    #endtest

    vec2 uv = gl_FragCoord.xy / resolution;
    uv += 0.1 * vNormal.xy * gFresnel * uDistortStrength * crange(length(uv - 0.5), 0.0, 0.9, 1.0, 0.0);
    vec3 insideColor = mix(mix(uInsideColor, uInsideColor2, uProgress), texture2D(tInside, uv).rgb, uInsideBlend);

    vec3 highlightColor = rgb2hsv(uColor);
    highlightColor += -0.02 + vRandom.x * 0.04;
    highlightColor = hsv2rgb(highlightColor);
    highlightColor *= 1.0 + matcap * uEnvBlend * vRandom.x;

    float highlight = step(vRandom.y, uRandomStep);
    float highlightLength = 0.4;
    float highlightPadding = 0.3;
    float highlightStrength = fract(vLength + time * 0.2 + vRandom.x * 20.0);
    highlightStrength = smoothstep(0.5 - highlightLength * (0.5 + highlightPadding), 0.5 - highlightLength * (0.5 - highlightPadding), highlightStrength) * smoothstep(0.5 + highlightLength * (0.5 + highlightPadding), 0.5 + highlightLength * (0.5 - highlightPadding), highlightStrength);
    highlightStrength *= smoothstep(0.0, 0.1, vLength) * smoothstep(1.0, 0.9, vLength);
    insideColor = mix(insideColor, highlightColor, highlight * highlightStrength);

    insideColor *= 1.0 + matcap * uEnvBlend * vRandom.x;
    insideColor.rgb *= mix(vec3(1.0), uFresnelColor, gFresnel);

    applyFog(insideColor);
    insideColor = blendOverlay(insideColor, uFresnelColor, getLight().r*3.0);

    insideColor = rgb2hsv(insideColor);
    //insideColor.x += crange(vRandom.x, 0.0, 1.0, -1.0, 1.0) * 0.007;
    //insideColor.z += crange(vRandom.y, 0.0, 1.0, -1.0, 1.0) * 0.005;
    insideColor = hsv2rgb(insideColor);

    gl_FragColor = vec4(insideColor, 1.0);
}{@}Level1TunnelFBRShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform sampler2D tAlpha;
uniform float uTexSpeed;
uniform float uProgress;

uniform vec3 uDistortStrength;
uniform float uDistortFrequency;
uniform float uDistortSpeed;
uniform vec3 uDistortStrength2;
uniform float uDistortFrequency2;
uniform float uDistortSpeed2;
uniform float uFBRStrength;
uniform float uFBRMix;

uniform vec2 uTile;
uniform vec3 uFresnelColor;
uniform vec4 uFresnelClamp;
uniform vec2 uFogDepth;

#!VARYINGS
varying vec2 vUv;
varying vec3 vPos;
varying float vDist;
varying vec3 vModelViewPos;

#!SHADER: Vertex
#require(range.glsl)
#require(simplenoise.glsl)
#require(fbr.vs)

void main() {
    vUv = uv;
    vec3 pos = position;
    vPos = pos;

    setupFBR(pos);

    float noise = cnoise(pos.xyz * uDistortFrequency + time * 0.5 * uDistortSpeed);
    float noise2 = cnoise(pos.xyz * uDistortFrequency2 + time * 0.5 * uDistortSpeed2);
    pos += noise * uDistortStrength * 0.1;
    pos += noise2 * uDistortStrength2 * 0.1;
    
    vNormal = normalize(normalMatrix * normal);

    vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
    vModelViewPos = mvPosition.xyz;

    vDist = length(cameraPosition - vec3(modelMatrix * vec4(pos, 1.0)));

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment
#require(range.glsl)
#require(fbr.fs)

void main() {
    vec2 uv = vUv * uTile;
    vec3 tex = texture2D(tMap, uv + time * uTexSpeed).rgb;
    float alpha = texture2D(tAlpha, uv + time * uTexSpeed).r;

    vec3 FBRtex = getFBR(tex).rgb * uFBRStrength;
    vec3 color = mix(tex, FBRtex, uFBRMix);
    
    float progress = mod(vPos.z*5.0, time*0.2)*uProgress;

    float fogDepth = crange(vDist, uFogDepth.x, uFogDepth.x + uFogDepth.y, 0.0, 1.0);

    gl_FragColor.rgb = color;
    gl_FragColor.a = (alpha - fogDepth);
}{@}Level1TunnelShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform sampler2D tNormal;
uniform sampler2D tAlpha;
uniform sampler2D tColors;
uniform float uNormalIntensity;
uniform float uBrightness;
uniform float uTexSpeed;
uniform float uProgress;

uniform vec3 uDistortStrength;
uniform float uDistortFrequency;
uniform float uDistortSpeed;
uniform vec3 uDistortStrength2;
uniform float uDistortFrequency2;
uniform float uDistortSpeed2;

uniform vec3 uAddColor;

uniform vec2 uTile;
uniform vec3 uFresnelColor;
uniform vec4 uFresnelClamp;
uniform vec2 uFogDepth;

#!VARYINGS
varying vec2 vUv;
varying vec3 vNormal;
varying vec3 vViewDir;
varying vec3 vPos;
varying float vDist;
varying vec3 vModelViewPos;

#!SHADER: Vertex
#require(range.glsl)
#require(simplenoise.glsl)

void main() {
    vUv = uv;
    vec3 pos = position;
    vPos = pos;

    float noise = cnoise(pos.xyz * uDistortFrequency + time * 0.5 * uDistortSpeed);
    float noise2 = cnoise(pos.xyz * uDistortFrequency2 + time * 0.5 * uDistortSpeed2);
    pos += noise * uDistortStrength * 0.1;
    pos += noise2 * uDistortStrength2 * 0.1;
    
    vNormal = normalize(normalMatrix * normal);

    vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
    vViewDir = -mvPosition.xyz;
    vModelViewPos = mvPosition.xyz;

    vDist = length(cameraPosition - vec3(modelMatrix * vec4(pos, 1.0)));

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment
#require(fresnel.glsl)
#require(range.glsl)
#require(normalmap.glsl)
#require(simplenoise.glsl)

void main() {
    vec2 uv = vUv * vec2(uTile.x, uTile.y);

    uv.y += time * uTexSpeed;

    vec3 color = texture2D(tMap, uv).rgb * uBrightness;
    vec3 color2 = texture2D(tMap, uv).rgb * 0.5;

    vec3 colormask = texture2D(tColors, uv).rgb * 0.12;

    float alpha = texture2D(tAlpha, uv).r;

    vec3 n1 = unpackNormal(-vModelViewPos, vNormal, tNormal, 0.9 * uNormalIntensity, 1.0, uv);
    vec3 n2 = unpackNormal(-vModelViewPos, vNormal, tNormal, 1.0 * uNormalIntensity, 1.0, uv);
    vec3 normalTex = (n1 + n2) / 2.0;

    float fresnel = getFresnel(normalTex, vViewDir, 1.0) * 1.0;
    float clampedFresnel = crange(fresnel, uFresnelClamp.x, uFresnelClamp.y, uFresnelClamp.z, uFresnelClamp.a);

    //color = mix(color, uFresnelColor, clampedFresnel);
    
    //float progress = mod(vPos.z*5.0, time*0.2)*uProgress;
    float progress = time * 0.2 * uProgress;

    float fogDepth = crange(vDist, uFogDepth.x, uFogDepth.x + uFogDepth.y, 0.0, 1.0);

    //color += color2;

    //lines blink
    color += 5.0 * colormask.r * crange(sin(time * 3.2 * uTexSpeed), -1.0, 1.0, -0.2, 1.0);
    color += 2.0 * colormask.g * crange(sin(time * 2.3 * uTexSpeed), -1.0, 1.0, -0.2, 1.0);
    color += 2.4 * colormask.b * crange(sin(time * 1.8 * uTexSpeed), -1.0, 1.0, -0.2, 1.0);


    color *= 1.0 + cnoise(vPos*2.0-time*0.8)*0.5;
    
    //color *= crange(sin(uv.y * 50.0 + time * 3.5 * uTexSpeed * 5.0), -1.0, 1.0, 0.2, 1.0); //gradient shading
    //color *= crange(sin(uv.y * 30.0 + time * 6.5 * uTexSpeed * 5.0), -1.0, 1.0, 1.0, 3.0); //gradient pulse

    color += uFresnelColor * clampedFresnel;

    //color = mix(color, vec3(0.2, 0.9, 0.1), progress); // debug progress
    //color += 2.0 * colormask.g * crange(sin(time * 2.3), -1.0, 1.0, -0.2, 1.0) * progress * uv.y * vec3(0.2, 0.9, 0.1);

    gl_FragColor.rgb = color;
    gl_FragColor.a = (1.0 - fogDepth);
}{@}Level2ParticleShader.glsl{@}#!ATTRIBUTES
attribute vec4 random;

#!UNIFORMS
uniform sampler2D tLifeData;
uniform sampler2D tPos;
uniform float uSize;
uniform vec2 uSizeRand;
uniform sampler2D tMap;
uniform float DPR;
uniform float uRes;
uniform vec3 uColor;
uniform vec2 uFade;
uniform float uHit;
uniform vec3 uDistortStrength;
uniform float uDistortFrequency;
uniform float uDistortSpeed;
uniform vec3 uDistortStrength2;
uniform float uDistortFrequency2;
uniform float uDistortSpeed2;
uniform float uProgress;

#!VARYINGS
varying vec2 vUv;
varying float vLife;
varying float vFade;
varying float vAlpha;
varying vec4 vRandom;
varying vec4 vMvPos;
varying float vDist;
varying vec3 vPos;
varying float vProgress;

#!SHADER: Vertex

#require(simplenoise.glsl)
#require(vfxcommon.vs)

void main() {
    vec4 decodedPos = texture2D(tPos, position.xy);
    vec3 pos = decodedPos.xyz;
    vPos = pos;

    float life = texture2D(tLifeData, position.xy).z;

    float progress = crange(time, 0.0, 9.0, 0.0, 1.0);
    vProgress = progress;

    float noise = cnoise(pos.xyz * uDistortFrequency + time * 0.5 * uDistortSpeed);
    float noise2 = cnoise(pos.xyz * uDistortFrequency2 + time * 0.5 * uDistortSpeed2);
    pos += (noise * uDistortStrength * 0.1) * (1.0 + progress);
    pos += noise2 * uDistortStrength2 * 0.1 * (1.0 + progress);

    pos.xy *= crange(progress, 0.0, 1.0, 0.1, 1.0);

    vFade = smoothstep(uFade.x, uFade.y, 1.0 - abs(life - 0.5));

    vDist = length(cameraPosition - vec3(modelMatrix * vec4(pos, 1.0)));
    vRandom = random;
    vAlpha = 1.0;
    vLife = crange(pos.y, 1.0, 0.0, 0.0, 1.0);

    vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
    gl_PointSize = 0.02 * DPR * uRes * uSize * crange(random.x, 0.0, 1.0, uSizeRand.x, uSizeRand.y) * (1000.0 / length(mvPosition.xyz)) * crange(vDist, 0.5, 1.0, 0.0, 1.5);
    gl_Position = projectionMatrix * mvPosition;

    setupVFX(pos);

    vMvPos = mvPosition;
}

#!SHADER: Fragment

#require(transformUV.glsl)
#require(vfxcommon.fs)
#require(rgb2hsv.fs)
#require(simplenoise.glsl)
#require(blendmodes.glsl)


void main() {
    vec2 uv = vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y);
    float alpha = smoothstep(0.0, 0.5, texture2D(tMap, uv).r);

    alpha *= vAlpha;
    alpha *= 1.0 + abs(0.3 * sin(time * 5.4 + vRandom.r * 18.3) + 1.6 * sin(time + vRandom.r * 10.7));

    alpha *= vFade;
    vec3 posRipple = vPos;
    posRipple.x *= 0.05;
    posRipple.y *= 0.05;
    posRipple.z *= 1.0;

    vec3 color = uColor;
    color = rgb2hsv(color);

    color.z += pow(cnoise(posRipple+time*1.0), 2.0) * crange(uProgress, 0.0, 0.1, 0.8, 0.25);
    color.z *= 1.0 + pow(abs(sin(vRandom.y*10.0+time*0.05)), 5000.0) * smoothstep(1.0, 0.5, uProgress) * 2.0 * smoothstep(0.0, 0.1, uProgress);
    color.z = mix(color.z, color.z*1.5 + sin(time*5.0+vRandom.x*20.0)*0.5, step(1.0 - smoothstep(0.0, 0.1, uProgress)*0.1, vRandom.y));
    color.z *= crange(uProgress, 0.0, 1.0, 1.0, 2.0);

    //color.z = mix(color.z, color.z*0.2, smoothstep(0.2, 0.0, uProgress));
    //color.z = mix(color.z, color.z*1.5, smoothstep(0.7, 1.0, uProgress));
    color.y = mix(color.y, color.y*0.7, smoothstep(0.2, 0.0, uProgress));

    color = hsv2rgb(color);

    color = mix(color, blendOverlay(color, vec3(1.0)), crange(vDist, 4.0, 10.0, uHit, 0.0) * (3.0 * pow(abs(sin(time*5.0+vRandom.x*20.0)), 4.0)));// * uHit;
    color *= smoothstep(1.5, 0.3, length(rotateUV(uv, -1.5)-0.2));

    applyFog(color);

    alpha *= smoothstep(1.2, 0.6, uProgress);

    if (alpha < 0.3) discard;

    gl_FragColor = vec4(color, alpha);
}{@}Level3Cubes.glsl{@}#!ATTRIBUTES
attribute float random;

#!UNIFORMS
uniform vec3 uColor0;
uniform vec3 uColor1;
uniform vec3 uLightDir;
uniform vec3 uHighlightColor;
uniform vec2 uDark;
uniform float uProgress;
uniform float uRandomStep;
uniform vec2 uGlassDistort2;
uniform vec2 uColorMix;
uniform sampler2D tInside;
uniform sampler2D tBG;
uniform sampler2D tMatcap;

#!VARYINGS
varying vec2 vUv;
varying vec3 vNormal;
varying vec3 vColor;
varying vec3 vWorldPos;
varying float vRandom;
varying vec3 vPos;

#!SHADER: Vertex

#require(lights.vs)
#require(vfxcommon.vs)
#require(matcap.vs)

void main() {
    vec3 pos = position;
    vNormal = normalMatrix * normal;
    vUv = uv;
    vPos = pos;

    vec3 lightPos = normalize(worldLight(uLightDir));
    float volume = clamp(dot(vNormal, lightPos), 0.0, 1.0);

    vec3 worldPos = vec3(modelMatrix * vec4(pos, 1.0));
    vWorldPos = worldPos;
    vColor = mix(uColor0, uColor1, volume);
    vColor *= crange(length(cameraPosition - worldPos), uDark.x, uDark.x + uDark.y, 0.0, 1.0);

    vRandom = random;

    setupVFX(pos);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(vfxcommon.fs)
#require(blendmodes.glsl)
#require(simplenoise.glsl)

void main() {
    vec3 color = vColor;
    color += getLight() * 0.8;
    color = mix(color, uHighlightColor, smoothstep(0.4, 1.5, uProgress));
    

    float len = length(cameraPosition - vWorldPos);

    vec2 guv =  gl_FragCoord.xy / resolution;
    guv += vNormal.xy * crange(len, 2.0, uFog.x, uGlassDistort2.x, uGlassDistort2.y);
    vec3 glass = mix(texture2D(tInside, guv).rgb, texture2D(tBG, gl_FragCoord.xy/resolution).rgb, uColorMix.x);
    glass = mix(color, glass, uColorMix.y);

    color = glass;
    color = mix(color, uHighlightColor, step(vRandom, uRandomStep));
    color = blendOverlay(color, uHighlightColor, smoothstep(0.5, 1.0, uProgress)*1.5);

    // float borderWidth = 0.002;
    // float padding = 0.0002;
    // float border = smoothstep(borderWidth, borderWidth-padding, vUv.x);
    // border += smoothstep(1.0-borderWidth, 1.0-borderWidth+padding, vUv.x);
    // borderWidth *= 2.0;
    // border += smoothstep(borderWidth, borderWidth-padding, vUv.y);
    // border += smoothstep(1.0-borderWidth, 1.0-borderWidth+padding, vUv.y);
    // color = blendOverlay(color, vec3(1.0), min(1.0, border)*smoothstep(-0.5, 1.0, cnoise(vPos*0.5+time*0.1))*1.0);

    color = mix(color, color*0.3, smoothstep(0.1, 0.0, uProgress));



    applyFog(color);


    //color *= vRandom.x;

    float alpha = smoothstep(0.95, 0.5, uProgress);
    gl_FragColor = vec4(color, alpha);
}{@}Level3BoxShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform vec3 uColor2;
uniform float uNoiseSpeed;
uniform float uNoiseScale;
uniform float uAlpha;
uniform vec3 uNoiseStretch;
uniform float uProgress;

#!VARYINGS
varying vec2 vUv;
varying vec3 vPos;

#!SHADER: Vertex
#require(vfxcommon.vs)

void main() {
    vUv = uv;
    vec3 pos = position;
    vPos = pos;
    setupVFX(pos);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(vfxcommon.fs)
#require(transformUV.glsl)
#require(simplenoise.glsl)
#require(eases.glsl)
#require(blendmodes.glsl)

float grid(vec2 st, float res, float width) {
  vec2 grid = fract(st*res);
  return (step(width,grid.x) * step(width*(resolution.x/resolution.y),grid.y));
}

void main() {
    vec3 pos = vPos;
    pos *= uNoiseStretch;
    float noise = cnoise(pos*uNoiseScale+time*uNoiseSpeed);

    vec3 color = uColor;
    color = mix(color, uColor2, smoothstep(-1.5, 2.0, noise)*smoothstep(0.4, 1.0, uProgress));

    //color *= smoothstep(-0.5, 1.0, vPos.z);
    //color *= smoothstep(0.4, 1.0, uProgress);

    applyFog(color);

    float alpha = uAlpha;
    alpha *= smoothstep(0.6, 1.3, uProgress);

    gl_FragColor.rgb = color;
    gl_FragColor.a = alpha;
}{@}ScanParticleShader.glsl{@}#!ATTRIBUTES
attribute vec4 random;

#!UNIFORMS
uniform sampler2D tLifeData;
uniform sampler2D tPos;
uniform float uSize;
uniform vec2 uSizeRand;
uniform sampler2D tMap;
uniform float DPR;
uniform float uRes;
uniform vec3 uColor;
uniform float uAlphaCutOff;
uniform vec2 uFade;
uniform float uProgress;

uniform vec3 uDistortStrength;
uniform float uDistortFrequency;
uniform float uDistortSpeed;
uniform vec3 uDistortStrength2;
uniform float uDistortFrequency2;
uniform float uDistortSpeed2;
uniform vec2 uFogDepth;

#!VARYINGS
varying vec2 vUv;
varying float vLife;
varying float vFade;
varying float vAlpha;
varying vec4 vRandom;
varying vec4 vMvPos;
varying float vDist;
varying vec3 vPos;

#!SHADER: Vertex

#require(range.glsl)
#require(simplenoise.glsl)

void main() {
    vec4 decodedPos = texture2D(tPos, position.xy);
    vec3 pos = decodedPos.xyz;
    vPos = pos;

    float life = texture2D(tLifeData, position.xy).z;

    vFade = smoothstep(uFade.x, uFade.y, 1.0 - abs(life - 0.5));

    vDist = length(cameraPosition - vec3(modelMatrix * vec4(pos, 1.0)));
    vRandom = random;
    vAlpha = 1.0;
    vLife = crange(pos.y, 1.0, 0.0, 0.0, 1.0);

    vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
    gl_PointSize = 0.02 * DPR * uRes * uSize * crange(random.x, 0.0, 1.0, uSizeRand.x, uSizeRand.y) * (1000.0 / length(mvPosition.xyz));
    gl_Position = projectionMatrix * mvPosition;

    vMvPos = mvPosition;
}

#!SHADER: Fragment

#require(range.glsl)
#require(transformUV.glsl)

void main() {

    vec2 uv = vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y);
    uv = rotateUV(uv, radians(360.0 * vRandom.z)-time*0.6);

    float alpha = smoothstep(0.0, 0.5, texture2D(tMap, uv).r);
    alpha *= vAlpha;
    alpha *= 1.0 + abs(0.3 * sin(time * 10.0 + vRandom.r * 18.3) + 1.6 * sin(time + vRandom.r * 10.7));

    vec3 color = uColor;
    color.rgb += vRandom.y*0.92;

    color.rgb *= 0.05 + uProgress * 2.0 * mix(vRandom.x*vRandom.z, 1.0, smoothstep(0.2, 1.0, uProgress));

    //alpha *= smoothstep(1.0, 0.0, vLife);
    float fogDepth = crange(vDist, uFogDepth.x, uFogDepth.x + uFogDepth.y, 1.0, 0.0);
    alpha *= vFade;
    color *= crange(sin(vPos.z * 3.0 + time * -5.5), -1.0, 1.0, 0.7, 3.2) * vec3(0.1, 0.1, 0.2);

    alpha *= smoothstep(1.2, 0.8, uProgress);
    alpha *= smoothstep(0.0, 1.0, vDist);

    if (alpha < 0.3) discard;

    gl_FragColor = vec4(color, alpha * fogDepth);
}{@}StructureSquareShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform vec3 uColor;
uniform float uSpeed;
uniform float uProgress;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;
varying vec3 vPos;


#!SHADER: Vertex

#require(vfxcommon.vs)

void main() {
    vUv = uv;
    vec3 pos = position;
    vPos = pos;

    setupVFX(pos);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(vfxcommon.fs)
#require(blendmodes.glsl)

void main() {
    vec3 color = texture2D(tMap, vUv).rgb;
    applyFog(color);

    color *= uColor;

    float alpha = crange(sin(-time * uSpeed + vPos.z * 0.7), -1.0, 1.0, 0.0, 1.0);
    alpha = pow(alpha, 3.0);
    alpha *= smoothstep(0.0, 0.1, uProgress) * mix(0.1, 1.0, uProgress) * smoothstep(6.0, 2.0, vPos.z);

    gl_FragColor.rgb = color;
    gl_FragColor.a = alpha * uAlpha;
}{@}AntimatterSpawn.fs{@}uniform float uMaxCount;
uniform float uSetup;
uniform float decay;
uniform vec2 decayRandom;
uniform sampler2D tLife;
uniform sampler2D tAttribs;
uniform float HZ;

#require(range.glsl)

void main() {
    vec2 uv = vUv;
    #test !window.Metal
    uv = gl_FragCoord.xy / fSize;
    #endtest

    vec4 data = texture2D(tInput, uv);

    if (vUv.x + vUv.y * fSize > uMaxCount) {
        gl_FragColor = vec4(9999.0);
        return;
    }

    vec4 life = texture2D(tLife, uv);
    vec4 random = texture2D(tAttribs, uv);
    if (life.x > 0.5) {
        data.xyz = life.yzw;
        data.x -= 999.0;
    } else {
        if (data.x < -500.0) {
            data.x = 1.0;
        } else {
            data.x -= 0.005 * decay * crange(random.w, 0.0, 1.0, decayRandom.x, decayRandom.y) * HZ;
        }
    }

    if (uSetup > 0.5) {
        data = vec4(0.0);
    }

    gl_FragColor = data;
}{@}CloudFogShader.glsl{@}#!ATTRIBUTES
attribute vec3 offset;
attribute vec4 random;

#!UNIFORMS
uniform sampler2D tMap;
uniform vec3 uColor;
uniform vec4 uQuaternion;
uniform float uScale;
uniform float uAlpha;
uniform float uCullDistance;
uniform float uSpeed;
uniform float uNoiseScale;
uniform float uNoiseStrength;
uniform float uNoiseTime;

#!VARYINGS
varying vec2 vUv;
varying float vAlpha;
varying vec3 vPos;


#!SHADER: Vertex

#require(instance.vs)
#require(range.glsl)
#require(rotation.glsl)

void main() {
    vUv = uv;
    vAlpha = uAlpha * crange(random.y, 0.0, 1.0, 0.5, 1.0) * 0.1;

    vec3 inPos = position;
    float rotation = radians((360.0 * random.z) + time*crange(random.w, 0.0, 1.0, -1.0, 1.0)*10.0*uSpeed);
    inPos = vec3(rotationMatrix(vec3(0.0, 0.0, 1.0), rotation) * vec4(inPos, 1.0));

    float scale = uScale * crange(random.x, 0.0, 1.0, 0.5, 1.5);
    vec3 pos = transformPosition(inPos, offset, scale, uQuaternion);
    float mDist = length(cameraPosition - vec3(modelMatrix * vec4(pos, 1.0)));

    vAlpha *= crange(mDist, uCullDistance*0.8, uCullDistance, 1.0, 0.0);
    vPos = pos;
    vAlpha *= crange(mDist, 8.0, 15.0, 0.0, 1.0);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(range.glsl)
#require(transformUV.glsl)
#require(simplenoise.glsl)

vec2 getUV() {
    float noise = cnoise((vPos * uNoiseScale) + time*uNoiseTime);
    float scale = 1.0 + (noise * uNoiseStrength * 0.1);

    return scaleUV(vUv, vec2(scale));
}

void main() {
    if (vAlpha < 0.01) {
        discard;
        return;
    }
    vec2 uv = uNoiseStrength > 0.0 ? getUV() : vUv;
    float mask = texture2D(tMap, uv).r;
    float padding = 0.3;
    mask *= crange(vUv.x, 0.0, padding, 0.0, 1.0) * crange(vUv.x, 1.0 - padding, 1.0, 1.0, 0.0);
    mask *= crange(vUv.y, 0.0, padding, 0.0, 1.0) * crange(vUv.y, 1.0 - padding, 1.0, 1.0, 0.0);

    gl_FragColor = vec4(uColor, mask * vAlpha);
}{@}curve3d.vs{@}uniform sampler2D tCurve;
uniform float uCurveSize;

vec2 getCurveUVFromIndex(float index) {
    float size = uCurveSize;
    vec2 ruv = vec2(0.0);
    float p0 = index / size;
    float y = floor(p0);
    float x = p0 - y;
    ruv.x = x;
    ruv.y = y / size;
    return ruv;
}

vec3 transformAlongCurve(vec3 pos, float idx) {
    vec3 offset = texture2D(tCurve, getCurveUVFromIndex(idx * (uCurveSize * uCurveSize))).xyz;
    vec3 p = pos;
    p.xz += offset.xz;
    return p;
}
{@}DOFBlur.glsl{@}#!ATTRIBUTES

#!UNIFORMS

#!VARYINGS

#!SHADER: dofcommon.fs
uniform sampler2D tDepth;
uniform float uStrength;
uniform float uRadius;
uniform float uNear;
uniform float uFar;
uniform float uBlurMin;
uniform float uQuality;
uniform vec3 uNearF;
uniform vec3 uFarF;

#require(depthvalue.fs)
#require(range.glsl)

float getDOFValue() {
    float depth = getDepthValue(tDepth, vUv, uNear, uFar);
    float strength = crange(depth, uNearF.x, uNearF.x + uNearF.y, 1.0, uBlurMin) * uNearF.z;
    strength = max(strength, crange(depth, uFarF.x, uFarF.x + uFarF.y, uBlurMin, 1.0) * uFarF.z);
    return strength;
}

#!SHADER: DOFBlurRadial.fs

#require(radialblur.fs)
#require(dofcommon.fs)

void main() {
    gl_FragColor = vec4(radialBlur(tDiffuse, vUv, uRadius * getDOFValue() * uStrength, vec2(1024), uQuality), 1.0);
}{@}fbr.fs{@}uniform sampler2D tMRO;
uniform sampler2D tMatcap;
uniform sampler2D tNormal;
uniform vec4 uLight;
uniform vec3 uColor;
uniform float uNormalStrength;

varying vec3 vNormal;
varying vec3 vPos;
varying vec3 vEyePos;
varying vec2 vUv;
varying vec3 vMPos;

const float PI = 3.14159265359;
const float PI2 = 6.28318530718;
const float RECIPROCAL_PI = 0.31830988618;
const float RECIPROCAL_PI2 = 0.15915494;
const float LOG2 = 1.442695;
const float EPSILON = 1e-6;
const float LN2 = 0.6931472;

vec2 reflectMatcapFBR(vec3 position, mat4 modelViewMatrix, vec3 normal) {
    vec4 p = vec4(position, 1.0);

    vec3 e = normalize(vec3(modelViewMatrix * p));
    vec3 n = normalize(normal);
    vec3 r = reflect(e, n);
    float m = 2.0 * sqrt(
    pow(r.x, 2.0) +
    pow(r.y, 2.0) +
    pow(r.z + 1.0, 2.0)
    );

    vec2 uv = r.xy / m + .5;

    return uv;
}

float prange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) {
    float oldRange = oldMax - oldMin;
    float newRange = newMax - newMin;
    return (((oldValue - oldMin) * newRange) / oldRange) + newMin;
}

float pcrange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) {
    return clamp(prange(oldValue, oldMin, oldMax, newMin, newMax), min(newMax, newMin), max(newMin, newMax));
}

vec3 unpackNormalFBR( vec3 eye_pos, vec3 surf_norm, sampler2D normal_map, float intensity, float scale, vec2 uv ) {
    surf_norm = normalize(surf_norm);

    vec3 q0 = dFdx( eye_pos.xyz );
    vec3 q1 = dFdy( eye_pos.xyz );
    vec2 st0 = dFdx( uv.st );
    vec2 st1 = dFdy( uv.st );

    vec3 S = normalize( q0 * st1.t - q1 * st0.t );
    vec3 T = normalize( -q0 * st1.s + q1 * st0.s );
    vec3 N = normalize( surf_norm );

    vec3 mapN = texture2D( normal_map, uv * scale ).xyz * 2.0 - 1.0;
    mapN.xy *= intensity;
    mat3 tsn = mat3( S, T, N );
    return normalize( tsn * mapN );
}

float geometricOcclusion(float NdL, float NdV, float roughness) {
    float r = roughness;
    float attenuationL = 2.0 * NdL / (NdL + sqrt(r * r + (1.0 - r * r) * (NdL * NdL)));
    float attenuationV = 2.0 * NdV / (NdV + sqrt(r * r + (1.0 - r * r) * (NdV * NdV)));
    return attenuationL * attenuationV;
}

float microfacetDistribution(float roughness, float NdH) {
    float roughnessSq = roughness * roughness;
    float f = (NdH * roughnessSq - NdH) * NdH + 1.0;
    return roughnessSq / (PI * f * f);
}

vec3 getFBR(vec3 baseColor, vec2 uv, vec2 normalUV) {
    vec3 mro = texture2D(tMRO, uv).rgb;
    float roughness = mro.g;

    vec3 normal = unpackNormalFBR(vEyePos, vNormal, tNormal, uNormalStrength, 1.0, normalUV);
    vec2 aUV = reflectMatcapFBR(vPos, projectionMatrix, normal);
    vec2 bUV = reflectMatcapFBR(vPos, modelMatrix, normal);
    vec2 mUV = mix(aUV, bUV, roughness);

    vec3 V = normalize(cameraPosition - vMPos);
    vec3 L = normalize(uLight.xyz);
    vec3 H = normalize(L + V);
    vec3 reflection = -normalize(reflect(V, normal));

    float NdL = pcrange(clamp(dot(normal, L), 0.001, 1.0), 0.0, 1.0, 0.4, 1.0);
    float NdV = pcrange(clamp(abs(dot(normal, V)), 0.001, 1.0), 0.0, 1.0, 0.4, 1.0);
    float NdH = clamp(dot(normal, H), 0.0, 1.0);
    float VdH = clamp(dot(V, H), 0.0, 1.0);

    float G = geometricOcclusion(NdL, NdV, roughness);
    float D = microfacetDistribution(roughness, NdH);

    vec3 specContrib = G * D / (4.0 * NdL * NdV) * uColor;
    vec3 color = NdL * specContrib * uLight.w;

    return ((baseColor * texture2D(tMatcap, mUV).rgb) + color) * mro.b;
}

vec3 getFBR(vec3 baseColor, vec2 uv) {
    return getFBR(baseColor, uv, uv);
}

vec3 getFBR(vec3 baseColor) {
    return getFBR(baseColor, vUv, vUv);
}

vec3 getFBR() {
    float roughness = texture2D(tMRO, vUv).g;

    vec3 normal = unpackNormalFBR(vEyePos, vNormal, tNormal, 1.0, 1.0, vUv);
    vec2 aUV = reflectMatcapFBR(vPos, projectionMatrix, normal);
    vec2 bUV = reflectMatcapFBR(vPos, modelMatrix, normal);
    vec2 mUV = mix(aUV, bUV, roughness);

    return texture2D(tMatcap, mUV).rgb;
}

vec3 getFBRSimplified() {
    vec2 mUV = reflectMatcapFBR(vPos, modelViewMatrix, vNormal);
    return texture2D(tMatcap, mUV).rgb;
}
{@}fbr.vs{@}varying vec3 vNormal;
varying vec3 vPos;
varying vec3 vEyePos;
varying vec2 vUv;
varying vec3 vMPos;

void setupFBR(vec3 p0) { //inlinemain
    vNormal = normalMatrix * normal;
    vUv = uv;
    vPos = p0;
    vec4 mPos = modelMatrix * vec4(p0, 1.0);
    vMPos = mPos.xyz / mPos.w;
    vEyePos = vec3(modelViewMatrix * vec4(p0, 1.0));
}{@}advectionManualFilteringShader.fs{@}varying vec2 vUv;
uniform sampler2D uVelocity;
uniform sampler2D uSource;
uniform vec2 texelSize;
uniform vec2 dyeTexelSize;
uniform float dt;
uniform float dissipation;
vec4 bilerp (sampler2D sam, vec2 uv, vec2 tsize) {
    vec2 st = uv / tsize - 0.5;
    vec2 iuv = floor(st);
    vec2 fuv = fract(st);
    vec4 a = texture2D(sam, (iuv + vec2(0.5, 0.5)) * tsize);
    vec4 b = texture2D(sam, (iuv + vec2(1.5, 0.5)) * tsize);
    vec4 c = texture2D(sam, (iuv + vec2(0.5, 1.5)) * tsize);
    vec4 d = texture2D(sam, (iuv + vec2(1.5, 1.5)) * tsize);
    return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y);
}
void main () {
    vec2 coord = vUv - dt * bilerp(uVelocity, vUv, texelSize).xy * texelSize;
    gl_FragColor = dissipation * bilerp(uSource, coord, dyeTexelSize);
    gl_FragColor.a = 1.0;
}{@}advectionShader.fs{@}varying vec2 vUv;
uniform sampler2D uVelocity;
uniform sampler2D uSource;
uniform vec2 texelSize;
uniform float dt;
uniform float dissipation;
void main () {
    vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;
    gl_FragColor = dissipation * texture2D(uSource, coord);
    gl_FragColor.a = 1.0;
}{@}backgroundShader.fs{@}varying vec2 vUv;
uniform sampler2D uTexture;
uniform float aspectRatio;
#define SCALE 25.0
void main () {
    vec2 uv = floor(vUv * SCALE * vec2(aspectRatio, 1.0));
    float v = mod(uv.x + uv.y, 2.0);
    v = v * 0.1 + 0.8;
    gl_FragColor = vec4(vec3(v), 1.0);
}{@}clearShader.fs{@}varying vec2 vUv;
uniform sampler2D uTexture;
uniform float value;
void main () {
    gl_FragColor = value * texture2D(uTexture, vUv);
}{@}colorShader.fs{@}uniform vec4 color;
void main () {
    gl_FragColor = color;
}{@}curlShader.fs{@}varying highp vec2 vUv;
varying highp vec2 vL;
varying highp vec2 vR;
varying highp vec2 vT;
varying highp vec2 vB;
uniform sampler2D uVelocity;
void main () {
    float L = texture2D(uVelocity, vL).y;
    float R = texture2D(uVelocity, vR).y;
    float T = texture2D(uVelocity, vT).x;
    float B = texture2D(uVelocity, vB).x;
    float vorticity = R - L - T + B;
    gl_FragColor = vec4(0.5 * vorticity, 0.0, 0.0, 1.0);
}{@}displayShader.fs{@}varying vec2 vUv;
uniform sampler2D uTexture;
void main () {
    vec3 C = texture2D(uTexture, vUv).rgb;
    float a = max(C.r, max(C.g, C.b));
    gl_FragColor = vec4(C, a);
}{@}divergenceShader.fs{@}varying highp vec2 vUv;
varying highp vec2 vL;
varying highp vec2 vR;
varying highp vec2 vT;
varying highp vec2 vB;
uniform sampler2D uVelocity;
void main () {
    float L = texture2D(uVelocity, vL).x;
    float R = texture2D(uVelocity, vR).x;
    float T = texture2D(uVelocity, vT).y;
    float B = texture2D(uVelocity, vB).y;
    vec2 C = texture2D(uVelocity, vUv).xy;
//    if (vL.x < 0.0) { L = -C.x; }
//    if (vR.x > 1.0) { R = -C.x; }
//    if (vT.y > 1.0) { T = -C.y; }
//    if (vB.y < 0.0) { B = -C.y; }
    float div = 0.5 * (R - L + T - B);
    gl_FragColor = vec4(div, 0.0, 0.0, 1.0);
}{@}fluidBase.vs{@}varying vec2 vUv;
varying vec2 vL;
varying vec2 vR;
varying vec2 vT;
varying vec2 vB;
uniform vec2 texelSize;

void main () {
    vUv = uv;
    vL = vUv - vec2(texelSize.x, 0.0);
    vR = vUv + vec2(texelSize.x, 0.0);
    vT = vUv + vec2(0.0, texelSize.y);
    vB = vUv - vec2(0.0, texelSize.y);
    gl_Position = vec4(position, 1.0);
}{@}gradientSubtractShader.fs{@}varying highp vec2 vUv;
varying highp vec2 vL;
varying highp vec2 vR;
varying highp vec2 vT;
varying highp vec2 vB;
uniform sampler2D uPressure;
uniform sampler2D uVelocity;
vec2 boundary (vec2 uv) {
    return uv;
    // uv = min(max(uv, 0.0), 1.0);
    // return uv;
}
void main () {
    float L = texture2D(uPressure, boundary(vL)).x;
    float R = texture2D(uPressure, boundary(vR)).x;
    float T = texture2D(uPressure, boundary(vT)).x;
    float B = texture2D(uPressure, boundary(vB)).x;
    vec2 velocity = texture2D(uVelocity, vUv).xy;
    velocity.xy -= vec2(R - L, T - B);
    gl_FragColor = vec4(velocity, 0.0, 1.0);
}{@}pressureShader.fs{@}varying highp vec2 vUv;
varying highp vec2 vL;
varying highp vec2 vR;
varying highp vec2 vT;
varying highp vec2 vB;
uniform sampler2D uPressure;
uniform sampler2D uDivergence;
vec2 boundary (vec2 uv) {
    return uv;
    // uncomment if you use wrap or repeat texture mode
    // uv = min(max(uv, 0.0), 1.0);
    // return uv;
}
void main () {
    float L = texture2D(uPressure, boundary(vL)).x;
    float R = texture2D(uPressure, boundary(vR)).x;
    float T = texture2D(uPressure, boundary(vT)).x;
    float B = texture2D(uPressure, boundary(vB)).x;
    float C = texture2D(uPressure, vUv).x;
    float divergence = texture2D(uDivergence, vUv).x;
    float pressure = (L + R + B + T - divergence) * 0.25;
    gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);
}{@}splatShader.fs{@}varying vec2 vUv;
uniform sampler2D uTarget;
uniform float aspectRatio;
uniform vec3 color;
uniform vec3 bgColor;
uniform vec2 point;
uniform vec2 prevPoint;
uniform float radius;
uniform float canRender;
uniform float uAdd;

float blendScreen(float base, float blend) {
    return 1.0-((1.0-base)*(1.0-blend));
}

vec3 blendScreen(vec3 base, vec3 blend) {
    return vec3(blendScreen(base.r, blend.r), blendScreen(base.g, blend.g), blendScreen(base.b, blend.b));
}

float l(vec2 uv, vec2 point1, vec2 point2) {
    vec2 pa = uv - point1, ba = point2 - point1;
    pa.x *= aspectRatio;
    ba.x *= aspectRatio;
    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
    return length(pa - ba * h);
}

float cubicOut(float t) {
    float f = t - 1.0;
    return f * f * f + 1.0;
}

void main () {
    vec3 splat = (1.0 - cubicOut(clamp(l(vUv, prevPoint.xy, point.xy) / radius, 0.0, 1.0))) * color;
    vec3 base = texture2D(uTarget, vUv).xyz;
    base *= canRender;

    vec3 outColor = mix(blendScreen(base, splat), base + splat, uAdd);
    gl_FragColor = vec4(outColor, 1.0);
}{@}vorticityShader.fs{@}varying vec2 vUv;
varying vec2 vL;
varying vec2 vR;
varying vec2 vT;
varying vec2 vB;
uniform sampler2D uVelocity;
uniform sampler2D uCurl;
uniform float curl;
uniform float dt;
void main () {
    float L = texture2D(uCurl, vL).x;
    float R = texture2D(uCurl, vR).x;
    float T = texture2D(uCurl, vT).x;
    float B = texture2D(uCurl, vB).x;
    float C = texture2D(uCurl, vUv).x;
    vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L));
    force /= length(force) + 0.0001;
    force *= curl * C;
    force.y *= -1.0;
//    force.y += 400.3;
    vec2 vel = texture2D(uVelocity, vUv).xy;
    gl_FragColor = vec4(vel + force * dt, 0.0, 1.0);
}{@}GlassShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tInside;
uniform float uTransparent;
uniform float uDistortStrength;

#!VARYINGS

#!SHADER: Vertex

#require(glass.vs)

void main() {
    setupGlass(position);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment

#require(glass.fs)

void main() {
    vec3 normal = normalMatrix * (gl_FrontFacing == false ? -vNormal : vNormal);

    gl_FragColor = getGlass(normal);

    if (uTransparent < 0.5) {
        vec2 uv = gl_FragCoord.xy / resolution;
        uv += 0.1 * vNormal.xy * gFresnel * uDistortStrength;
        vec3 color = texture2D(tInside, uv).rgb;
        gl_FragColor.rgb = mix(gl_FragColor.rgb, color, 1.0 - gl_FragColor.a);
    }
}{@}glass.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tEnv;
uniform float uRefractionRatio;
uniform float uReflectScale;
uniform float uRatio;
uniform float uAttenuation;
uniform float uAlpha;
uniform float uShininess;
uniform float uFresnelPow;
uniform float uFresnelAlpha;
uniform float uEnvBlend;
uniform vec2 uSpecAdd;
uniform vec3 uPhongColor;
uniform vec3 uFresnelColor;
uniform vec3 uLightDir;

#!VARYINGS
varying vec3 vReflect;
varying vec3 vRefract;
varying vec3 vWorldPos;
varying vec3 vNormal;
varying vec3 vViewDir;
varying vec3 vLightDir;

#!SHADER: Vertex

#require(refl.vs)
#require(lights.vs)

void setupGlass(vec3 pos) {
    vec4 worldPos = modelMatrix * vec4(pos * uReflectScale, 1.0);
    vWorldPos = worldPos.xyz;
    vNormal = normal;
    vViewDir = -vec3(modelViewMatrix * vec4(pos, 1.0));
    vReflect = reflection(worldPos);
    vRefract = refraction(worldPos, uRefractionRatio);
    vLightDir = normalize(worldLight(uLightDir));
}

#!SHADER: Fragment

#require(refl.fs)
#require(phong.fs)
#require(fresnel.glsl)

float gFresnel;

vec4 getGlass(vec3 normal) {
    vec3 specLight = phong(1.0, vec3(1.0), uPhongColor, uShininess, uAttenuation, normal, vLightDir, vViewDir);
    gFresnel = getFresnel(normal, vViewDir, uFresnelPow);

    vec3 reflected = envColorEqui(tEnv, vReflect).rgb;
    vec3 refracted = envColorEqui(tEnv, vRefract).rgb;
    vec4 color = vec4(mix(reflected, refracted, uRatio) * uEnvBlend, uAlpha);
    color.rgb += specLight * uSpecAdd.x;
    color.rgb *= mix(vec3(1.0), uFresnelColor, gFresnel);
    color.a += specLight.r * uSpecAdd.y;
    color.a += uFresnelAlpha * gFresnel;

    return color;
}{@}Line.glsl{@}#!ATTRIBUTES
attribute vec3 previous;
attribute vec3 next;
attribute float side;
attribute float width;
attribute float lineIndex;
attribute vec2 uv2;

#!UNIFORMS
uniform float uLineWidth;
uniform float uBaseWidth;
uniform float uOpacity;
uniform vec3 uColor;

#!VARYINGS
varying float vLineIndex;
varying vec2 vUv;
varying vec2 vUv2;
varying vec3 vColor;
varying float vOpacity;
varying float vWidth;
varying float vDist;
varying float vFeather;


#!SHADER: Vertex

#require(conditionals.glsl)

//params

vec2 fix(vec4 i, float aspect) {
    vec2 res = i.xy / i.w;
    res.x *= aspect;
    return res;
}

void main() {
    float aspect = resolution.x / resolution.y;

    vUv = uv;
    vUv2 = uv2;
    vLineIndex = lineIndex;
    vColor = uColor;
    vOpacity = uOpacity;
    vFeather = 0.1;

    vec3 pos = position;
    vec3 prevPos = previous;
    vec3 nextPos = next;
    float lineWidth = 1.0;
    //main

    //startMatrix
    mat4 m = projectionMatrix * modelViewMatrix;
    vec4 finalPosition = m * vec4(pos, 1.0);
    vec4 pPos = m * vec4(prevPos, 1.0);
    vec4 nPos = m * vec4(nextPos, 1.0);
    //endMatrix

    vec2 currentP = fix(finalPosition, aspect);
    vec2 prevP = fix(pPos, aspect);
    vec2 nextP = fix(nPos, aspect);

    float w = uBaseWidth * uLineWidth * width * lineWidth;
    vWidth = w;

    vec2 dirNC = normalize(currentP - prevP);
    vec2 dirPC = normalize(nextP - currentP);

    vec2 dir1 = normalize(currentP - prevP);
    vec2 dir2 = normalize(nextP - currentP);
    vec2 dirF = normalize(dir1 + dir2);

    vec2 dirM = mix(dirPC, dirNC, when_eq(nextP, currentP));
    vec2 dir = mix(dirF, dirM, clamp(when_eq(nextP, currentP) + when_eq(prevP, currentP), 0.0, 1.0));

    //direction
    vec2 normal = vec2(-dir.y, dir.x);
    normal.x /= aspect;
    normal *= 0.5 * w;

    vDist = finalPosition.z / 10.0;

    finalPosition.xy += normal * side;
    gl_Position = finalPosition;
}

#!SHADER: Fragment

//fsparams

void main() {
    float d = (1.0 / (5.0 * vWidth + 1.0)) * vFeather * (vDist * 5.0 + 0.5);
    vec2 uvButt = vec2(0.0, vUv.y);
    float buttLength = 0.5 * vWidth;
    uvButt.x = min(0.5, vUv2.x / buttLength) + (0.5 - min(0.5, (vUv2.y - vUv2.x) / buttLength));
    float round = length(uvButt - 0.5);
    float alpha = smoothstep(0.5, 0.5 - d, round);

    vec3 color = vColor;

    gl_FragColor.rgb = color;
    gl_FragColor.a = alpha;
    gl_FragColor.a *= vOpacity;

    //fsmain

    if (gl_FragColor.a < 0.1) discard;
}
{@}mousefluid.fs{@}uniform sampler2D tFluid;
uniform sampler2D tFluidMask;

vec2 getFluidVelocity() {
    float fluidMask = smoothstep(0.1, 0.7, texture2D(tFluidMask, vUv).r);
    return texture2D(tFluid, vUv).xy * fluidMask;
}

vec3 getFluidVelocityMask() {
    float fluidMask = smoothstep(0.1, 0.7, texture2D(tFluidMask, vUv).r);
    return vec3(texture2D(tFluid, vUv).xy * fluidMask, fluidMask);
}{@}ProtonAntimatter.fs{@}uniform sampler2D tOrigin;
uniform sampler2D tAttribs;
uniform float uMaxCount;
//uniforms

#require(range.glsl)
//requires

void main() {
    vec2 uv = vUv;
    #test !window.Metal
    uv = gl_FragCoord.xy / fSize;
    #endtest

    vec3 origin = texture2D(tOrigin, uv).xyz;
    vec4 inputData = texture2D(tInput, uv);
    vec3 pos = inputData.xyz;
    vec4 random = texture2D(tAttribs, uv);
    float data = inputData.w;

    if (vUv.x + vUv.y * fSize > uMaxCount) {
        gl_FragColor = vec4(9999.0);
        return;
    }

    //code

    gl_FragColor = vec4(pos, data);
}{@}ProtonAntimatterLifecycle.fs{@}uniform sampler2D tOrigin;
uniform sampler2D tAttribs;
uniform sampler2D tSpawn;
uniform float uMaxCount;
//uniforms

#require(range.glsl)
//requires

void main() {
    vec3 origin = texture2D(tOrigin, vUv).rgb;
    vec4 inputData = texture2D(tInput, vUv);
    vec3 pos = inputData.xyz;
    vec4 random = texture2D(tAttribs, vUv);
    float data = inputData.w;

    if (vUv.x + vUv.y * fSize > uMaxCount) {
        gl_FragColor = vec4(9999.0);
        return;
    }

    vec4 spawn = texture2D(tSpawn, vUv);
    float life = spawn.x;

    if (spawn.x < -500.0) {
        pos = spawn.xyz;
        pos.x += 999.0;
        spawn.x = 1.0;
        gl_FragColor = vec4(pos, data);
        return;
    }

    //abovespawn
    if (spawn.x <= 0.0) {
        pos.x = 9999.0;
        gl_FragColor = vec4(pos, data);
        return;
    }

    //abovecode
    //code

    gl_FragColor = vec4(pos, data);
}{@}ProtonNeutrino.fs{@}//uniforms

#require(range.glsl)
//requires

void main() {
    //code
}{@}ProtonTube.glsl{@}#!ATTRIBUTES
attribute float angle;
attribute vec2 tuv;
attribute float cIndex;
attribute float cNumber;

#!UNIFORMS
uniform sampler2D tPos;
uniform sampler2D tLife;
uniform float radialSegments;
uniform float thickness;
uniform float taper;

#!VARYINGS
varying float vLength;
varying vec3 vNormal;
varying vec3 vViewPosition;
varying vec3 vPos;
varying vec2 vUv;
varying float vIndex;
varying float vLife;

#!SHADER: Vertex

//neutrinoparams

#require(ProtonTubesUniforms.fs)
#require(range.glsl)
#require(conditionals.glsl)

void main() {
    float headIndex = getIndex(cNumber, 0.0, lineSegments);
    vec2 iuv = getUVFromIndex(headIndex, textureSize);
    float life = texture2D(tLife, iuv).x;
    vLife = life;

    float scale = 1.0;
    //neutrinovs
    vec2 volume = vec2(thickness * 0.065 * scale);

    vec3 transformed;
    vec3 objectNormal;

    //extrude tube
    float posIndex = getIndex(cNumber, cIndex, lineSegments);
    float nextIndex = getIndex(cNumber, cIndex + 1.0, lineSegments);

    vLength = cIndex / (lineSegments - 2.0);
    vIndex = cIndex;

    vec3 current = texture2D(tPos, getUVFromIndex(posIndex, textureSize)).xyz;
    vec3 next = texture2D(tPos, getUVFromIndex(nextIndex, textureSize)).xyz;

    vec3 T = normalize(next - current);
    vec3 B = normalize(cross(T, next + current));
    vec3 N = -normalize(cross(B, T));

    float tubeAngle = angle;
    float circX = cos(tubeAngle);
    float circY = sin(tubeAngle);

    volume *= crange(vLength, 0.0, taper, 0.85, 1.0);

    objectNormal.xyz = normalize(B * circX + N * circY);
    transformed.xyz = current + B * volume.x * circX + N * volume.y * circY;
    //extrude tube

    vec3 transformedNormal = normalMatrix * objectNormal;
    vNormal = normalize(transformedNormal);
    vUv = tuv.yx;

    vec3 pos = transformed;
    vec4 mvPosition = modelViewMatrix * vec4(transformed, 1.0);
    vViewPosition = -mvPosition.xyz;
    vPos = pos;
    gl_Position = projectionMatrix * mvPosition;

    //neutrinovspost
}

#!SHADER: Fragment
void main() {
    gl_FragColor = vec4(1.0);
}{@}ProtonTubesMain.fs{@}void main() {
    vec3 index = getData(tIndices, vUv);

    float CHAIN = index.x;
    float LINE = index.y;
    float HEAD = index.z;

    if (HEAD > 0.9) {

        //main

    } else {

        float followIndex = getIndex(LINE, CHAIN-1.0, lineSegments);
        float headIndex = getIndex(LINE, 0.0, lineSegments);
        vec3 followPos = texture2D(tInput, getUVFromIndex(followIndex, textureSize)).xyz;
        vec4 followSpawn = texture2D(tSpawn, getUVFromIndex(headIndex, textureSize));

        if (followSpawn.x <= 0.0) {
            pos.x = 9999.0;
            gl_FragColor = vec4(pos, data);
            return;
        }

        if (length(followPos - pos) > uResetDelta) {
            followPos = texture2D(tInput, getUVFromIndex(headIndex, textureSize)).xyz;
            pos = followPos;
        }

        pos += (followPos - pos) * (uLerp * timeScale * HZ);
    }
}{@}ProtonTubesUniforms.fs{@}uniform sampler2D tIndices;
uniform float textureSize;
uniform float lineSegments;
uniform float uLerp;
uniform float uResetDelta;

vec2 getUVFromIndex(float index, float textureSize) {
    float size = textureSize;
    vec2 ruv = vec2(0.0);
    float p0 = index / size;
    float y = floor(p0);
    float x = p0 - y;
    ruv.x = x;
    ruv.y = y / size;
    return ruv;
}

float getIndex(float line, float chain, float lineSegments) {
    return (line * lineSegments) + chain;
}{@}SceneLayout.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex
void main() {
    vec3 pos = position;
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment
void main() {
    gl_FragColor = texture2D(tMap, vUv);
    gl_FragColor.a *= uAlpha;
    gl_FragColor.rgb /= gl_FragColor.a;
}{@}GLUIShape.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform float uAlpha;

#!VARYINGS

#!SHADER: Vertex
void main() {
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment
void main() {
    gl_FragColor = vec4(uColor, uAlpha);
}{@}GLUIShapeBitmap.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform sampler2D tMask;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment
void main() {
    gl_FragColor = texture2D(tMap, vUv) * texture2D(tMask, vUv).a;
    gl_FragColor.a *= uAlpha;
}{@}SplineParticleInstance.glsl{@}#!ATTRIBUTES
attribute vec2 lookup;

#!UNIFORMS
uniform sampler2D tPos;

#!VARYINGS

#!SHADER: Vertex

#require(instance.vs)
#require(rotation.glsl)

void main() {
    vec3 offset = texture2D(tPos, lookup).xyz;
    vec3 p = vec3(rotationMatrix(vec3(0.0, 0.0, 1.0), radians(time*10000000.0)) * vec4(position, 1.0));
    vec3 pos = transformPosition(p, offset);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment
void main() {
    gl_FragColor = vec4(1.0);
}{@}SplineParticleLife.fs{@}uniform sampler2D tAttribs;
uniform sampler2D tPos;
uniform sampler2D tOrigin;
uniform float uMaxCount;
uniform float uSplineCount;
uniform float uSetup;
uniform float uDecayRate;
uniform float uTimeMultiplier;
uniform float uIHold;
uniform vec2 uDecayRange;
uniform vec2 uRelease;
uniform float uStartOffset;
uniform vec2 uFlowRange;
uniform vec2 uSplineSpeed;
uniform float uInfinite;
uniform float uDelayStart;
uniform float uMaxDelay;
uniform float uMaxSDelay;
uniform float uHoldBack;
uniform float uHoldBack2;
uniform float uStartSpacing;
uniform vec4 uLifeSlow;
uniform float HZ;

#require(range.glsl)
#require(conditionals.glsl)
#require(simplenoise.glsl)

float sround(float i) {
    return floor(i + 0.5);
}

float randomSeed(float seed) {
    float n = sin(seed) * 10.0;
    return n - floor(n);
}

float srand(float seed, float min, float max) {
    return (min + randomSeed(seed) * (max - min));
}

void main() {
    vec2 uv = vUv;

    if (vUv.x + vUv.y * fSize > uMaxCount) {
        gl_FragColor = vec4(9999.0);
        return;
    }

    vec4 inputData = getData4(tInput, uv);
    vec4 random = getData4(tAttribs, uv);
    vec4 random2 = (getData4(tOrigin, uv) / 2.0) + 0.5;
    vec4 pos = getData4(tPos, uv);

    vec4 outputData;
    outputData.x = sround(crange(random.x, 0.0, 1.0, 0.0, uSplineCount-1.0));

//    float decay = crange(random.w, 0.0, 1.0, uDecayRange.x, uDecayRange.y);
//
//    outputData.y = inputData.y + mix(0.02 * uDecaySpeed.x * decay, 0.002 * uDecaySpeed.y * decay, when_gt(inputData.y, 0.999));
//    outputData.y = clamp(outputData.y, 0.0, 2.0);

    outputData.y = inputData.y - (0.01 * uDecayRate * mix(uDecayRange.x, uDecayRange.y, random2.y) * timeScale * HZ);
    outputData.y = clamp(outputData.y, 0.0, 1.0);

    if (uSetup > 0.5) {
        outputData.z = crange(random.w, 0.0, 1.0, 0.0, uStartOffset);
        outputData.z += srand(outputData.x, 0.0, uStartSpacing);
    } else {
        float delayed = 1.0;
        float delayedSpline = 1.0;

        float sRandom = crange(cnoise(vec2(random.x)), -1.0, 1.0, 0.0, 1.0);

        bool isStarting = inputData.z == 0.0;

        if (uDelayStart > 0.0) {
            delayed = time - uDelayStart > uMaxDelay * random2.y ? 1.0 : 0.0;
            delayedSpline = time - uDelayStart > uMaxSDelay * random.x ? 1.0 : 0.0;
        }

        float lifeSlow = crange(inputData.z, uLifeSlow.x, uLifeSlow.y, uLifeSlow.z, uLifeSlow.w);
        outputData.z = inputData.z + (0.001 * timeScale * uTimeMultiplier * lifeSlow * HZ * crange(random2.z, 0.0, 1.0, uFlowRange.x, uFlowRange.y) * crange(sRandom, 0.0, 1.0, uSplineSpeed.x, uSplineSpeed.y));

        if (uRelease.y > 1.0) {
            if (inputData.z < 0.001 || inputData.z > 1.0) {
                float minR = uRelease.x / uRelease.y;
                float maxR = (uRelease.x+1.0) / uRelease.y;
                if (random.w < minR || random.w > maxR) {
                    outputData.z = 0.0;
                }
            }
        }
//
        if (isStarting) outputData.z *= delayed * delayedSpline * step(1.0 - ((1.0 - uHoldBack) * (1.0 - uHoldBack2)), random2.x);

        if (outputData.z > 1.0) {
            outputData.w = 0.0;
            if (uInfinite > 0.5) outputData.z = 0.0;
        } else if (outputData.z < 0.01) {
            outputData.y = 1.0;
        }

        if (uIHold > 0.5) outputData.z = 0.0;
    }

    gl_FragColor = outputData;
}{@}SplineParticlePreset.fs{@}void main() {
sRandom = random;
sOrigin = origin;

float travel = texture2D(tLife, vUv).z;
vec3 target = getSplinePos(travel);

if (uSetup > 0.5 || travel < 0.001) {
    pos = target;
}

pos += (target - pos) * 0.07 * HZ;
}{@}splineparticles.fs{@}uniform sampler2D tSpline;
uniform sampler2D tLife;
uniform float uSplineTexSize;
uniform float uPerSpline;
uniform float uSplineCount;
uniform float uInfinite;
uniform float uSetup;

vec4 sRandom;
vec3 sOrigin;

float splinenoise(vec3 v) {
    float t = v.z * 0.3;
    v.y *= 0.8;
    float noise = 0.0;
    float s = 0.5;
    noise += range(sin(v.x * 0.9 / s + t * 10.0) + sin(v.x * 2.4 / s + t * 15.0) + sin(v.x * -3.5 / s + t * 4.0) + sin(v.x * -2.5 / s + t * 7.1), -1.0, 1.0, -0.3, 0.3);
    noise += range(sin(v.y * -0.3 / s + t * 18.0) + sin(v.y * 1.6 / s + t * 18.0) + sin(v.y * 2.6 / s + t * 8.0) + sin(v.y * -2.6 / s + t * 4.5), -1.0, 1.0, -0.3, 0.3);
    return noise;
}

float sround(float i) {
    return floor(i + 0.5);
}

float randomSeed(float seed) {
    float n = sin(seed) * 10000000.0;
    return n - floor(n);
}

float srand(float seed, float min, float max) {
    return sround((min + randomSeed(seed) * (max - min)));
}

float getSplineIndex() {
    return sround(crange(sRandom.x, 0.0, 1.0, 0.0, uSplineCount-1.0));
}

vec2 getSplineLookupUV(float index, float time) {
    float pixel = (index * uPerSpline) + (time * uPerSpline);

    float size = uSplineTexSize;
    float p0 = pixel / size;
    float y = floor(p0);
    float x = p0 - y;

    vec2 uv = vec2(0.0);
    uv.x = x;
    uv.y = y / size;
    return uv;
}

float ssineOut(float t) {
    return sin(t * 1.5707963267948966);
}

float scnoise(vec3 v) {
    float t = v.z * 0.3;
    v.y *= 0.8;
    float noise = 0.0;
    float s = 0.5;
    noise += range(sin(v.x * 0.9 / s + t * 10.0) + sin(v.x * 2.4 / s + t * 15.0) + sin(v.x * -3.5 / s + t * 4.0) + sin(v.x * -2.5 / s + t * 7.1), -1.0, 1.0, -0.3, 0.3);
    noise += range(sin(v.y * -0.3 / s + t * 18.0) + sin(v.y * 1.6 / s + t * 18.0) + sin(v.y * 2.6 / s + t * 8.0) + sin(v.y * -2.6 / s + t * 4.5), -1.0, 1.0, -0.3, 0.3);
    return noise;
}

vec3 getSplinePosRaw(float time) {
    float step = 1.0 / uPerSpline;
    float index = getSplineIndex();
    vec2 uv0 = getSplineLookupUV(index, time);
    vec2 uv1 = getSplineLookupUV(index, min(1.0, time + step));
    float interpolate = mod(time, step) * uPerSpline;

    vec3 cpos = texture2D(tSpline, uv0).xyz;
    vec3 npos = texture2D(tSpline, uv1).xyz;
    vec3 pos = mix(cpos, npos, interpolate);

    if (uSCurlNoiseSpeed > 0.0) {
        pos += curlNoise((pos * uSCurlNoiseScale*0.1) + (time * uSCurlTimeScale*0.1)) * uSCurlNoiseSpeed * 0.01 * HZ;
    }

    return pos;
}

vec3 getSplinePos(float time) {
    vec3 pos = getSplinePosRaw(time);
    pos += sOrigin * 0.5 * uSplineThickness;
    return pos;
}

vec3 getSplinePos(float time, vec3 orgn) {
    vec3 pos = getSplinePosRaw(time) + (crange(orgn, vec3(0.0), vec3(1.0), vec3(-1.0), vec3(1.0)) * 0.5 * uSplineThickness);
    return pos;
}

{@}splineshader.glsl{@}uniform sampler2D tSpline;
uniform float uSplineTexSize;
uniform float uPerSpline;

#require(conditionals.glsl)

float sround(float i) {
    return floor(i + 0.5);
}

vec2 getSplineLookupUV(float index, float time) {
    float pixel = (index * uPerSpline) + (time * uPerSpline);

    float size = uSplineTexSize;
    float p0 = pixel / size;
    float y = floor(p0);
    float x = p0 - y;

    vec2 uv = vec2(0.0);
    uv.x = x;
    uv.y = y / size;
    return uv;
}

vec3 getSplinePos(float index, float time) {
    vec2 uv = getSplineLookupUV(index, time);
    vec3 pos = texture2D(tSpline, uv).xyz;
    return pos;
}

float isMoving(float index, float time) {
    vec3 cpos = getSplinePos(index, time);
    vec3 npos = getSplinePos(index, time + (1.0 / uPerSpline));

    float moving = when_gt(length(cpos - npos), 0.001);
    moving = mix(moving, 1.0, when_gt(time, 0.5));

    return moving;
}{@}Text3D.glsl{@}#!ATTRIBUTES
attribute vec3 animation;

#!UNIFORMS
uniform sampler2D tMap;
uniform vec3 uColor;
uniform float uAlpha;
uniform vec3 uTranslate;
uniform vec3 uRotate;
uniform float uTransition;
uniform float uWordCount;
uniform float uLineCount;
uniform float uLetterCount;
uniform float uByWord;
uniform float uByLine;
uniform float uPadding;
uniform vec3 uBoundingMin;
uniform vec3 uBoundingMax;

#!VARYINGS
varying float vTrans;
varying vec2 vUv;
varying vec3 vPos;

#!SHADER: Vertex

#require(range.glsl)
#require(eases.glsl)
#require(rotation.glsl)
#require(conditionals.glsl)

void main() {
    vUv = uv;
    vTrans = 1.0;

    vec3 pos = position;

    if (uTransition < 5.0) {
        float padding = uPadding;
        float letter = (animation.x + 1.0) / uLetterCount;
        float word = (animation.y + 1.0) / uWordCount;
        float line = (animation.z + 1.0) / uLineCount;

        float letterTrans = crange(uTransition, letter - padding, letter + padding, 0.0, 1.0);
        float wordTrans = crange(uTransition, word - padding, word + padding, 0.0, 1.0);
        float lineTrans = crange(uTransition, line - padding, line + padding, 0.0, 1.0);

        vTrans = mix(cubicOut(letterTrans), cubicOut(wordTrans), uByWord);
        vTrans = mix(vTrans, cubicOut(lineTrans), uByLine);

        float invTrans = (1.0 - vTrans);
        vec3 nRotate = normalize(uRotate);
        vec3 axisX = vec3(1.0, 0.0, 0.0);
        vec3 axisY = vec3(0.0, 1.0, 0.0);
        vec3 axisZ = vec3(0.0, 0.0, 1.0);
        vec3 axis = mix(axisX, axisY, when_gt(nRotate.y, nRotate.x));
        axis = mix(axis, axisZ, when_gt(nRotate.z, nRotate.x));
        pos = vec3(vec4(position, 1.0) * rotationMatrix(axis, radians(max(max(uRotate.x, uRotate.y), uRotate.z) * invTrans)));
        pos += uTranslate * invTrans;
    }

    vPos = pos;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(range.glsl)
#require(msdf.glsl)
#require(simplenoise.glsl)

vec2 getBoundingUV() {
    vec2 uv;
    uv.x = crange(vPos.x, uBoundingMin.x, uBoundingMax.x, 0.0, 1.0);
    uv.y = crange(vPos.y, uBoundingMin.y, uBoundingMax.y, 0.0, 1.0);
    return uv;
}

void main() {
    float alpha = msdf(tMap, vUv);

    //float noise = 0.5 + smoothstep(-1.0, 1.0, cnoise(vec3(vUv*50.0, time* 0.3))) * 0.5;

    gl_FragColor.rgb = uColor;
    gl_FragColor.a = alpha * uAlpha * vTrans;
}
{@}UnrealBloom.fs{@}uniform sampler2D tUnrealBloom;

vec3 getUnrealBloom(vec2 uv) {
    return texture2D(tUnrealBloom, uv).rgb;
}{@}UnrealBloomComposite.glsl{@}#!ATTRIBUTES

#!UNIFORMS

uniform sampler2D blurTexture1;
uniform float bloomStrength;
uniform float bloomRadius;
uniform vec3 bloomTintColor;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex.vs
void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}

#!SHADER: Fragment.fs

float lerpBloomFactor(const in float factor) {
    float mirrorFactor = 1.2 - factor;
    return mix(factor, mirrorFactor, bloomRadius);
}

void main() {
    gl_FragColor = bloomStrength * (lerpBloomFactor(1.0) * vec4(bloomTintColor, 1.0) * texture2D(blurTexture1, vUv));
}{@}UnrealBloomGaussian.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D colorTexture;
uniform vec2 texSize;
uniform vec2 direction;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex.vs
void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}

#!SHADER: Fragment.fs

float gaussianPdf(in float x, in float sigma) {
    return 0.39894 * exp(-0.5 * x * x / (sigma * sigma)) / sigma;
}

void main() {
    vec2 invSize = 1.0 / texSize;
    float fSigma = float(SIGMA);
    float weightSum = gaussianPdf(0.0, fSigma);
    vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;
    for(int i = 1; i < KERNEL_RADIUS; i ++) {
        float x = float(i);
        float w = gaussianPdf(x, fSigma);
        vec2 uvOffset = direction * invSize * x;
        vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;
        vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;
        diffuseSum += (sample1 + sample2) * w;
        weightSum += 2.0 * w;
    }
    gl_FragColor = vec4(diffuseSum/weightSum, 1.0);
}{@}UnrealBloomLuminosity.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tDiffuse;
uniform vec3 defaultColor;
uniform float defaultOpacity;
uniform float luminosityThreshold;
uniform float smoothWidth;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex.vs
void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}

#!SHADER: Fragment.fs

#require(luma.fs)

void main() {
    vec4 texel = texture2D(tDiffuse, vUv);
    float v = luma(texel.xyz);
    vec4 outputColor = vec4(defaultColor.rgb, defaultOpacity);
    float alpha = smoothstep(luminosityThreshold, luminosityThreshold + smoothWidth, v);
    gl_FragColor = mix(outputColor, texel, alpha);
}{@}UnrealBloomPass.fs{@}#require(UnrealBloom.fs)

void main() {
    vec4 color = texture2D(tDiffuse, vUv);
    color.rgb += getUnrealBloom(vUv);
    gl_FragColor = color;
}{@}CatcherBlastShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
// uniform sampler2D tNoise;
uniform vec3 uColor;
uniform float uBlast;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex
void main() {
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    vUv = uv;
}

#!SHADER: Fragment

#require(transformUV.glsl)
#require(simplenoise.glsl)

float sdCircle(vec2 p, float r) {
    return length(p) - r;
}

float opOnion(float d, float r) {
  return abs(d) - r;
}

void main() {
    vec2 uv = vUv;
    float b = (uBlast - 0.25) / 1.6;

    //uv += cnoise(vec3(uv * 5.0 * (1.0 - b * 0.5), time*0.5)) * 0.02;

    float d = sdCircle(uv - 0.5, b);
    d = opOnion(d, 0.02);
    d = smoothstep(0.86, 1.0, 1.0 - d);
    
    float a = d;
    a *= smoothstep(0.6, 1.0, 1.0 - b);

    // vec2 nUv = scaleUV(uv, vec2(b * 4.0 + 0.5));
    // float n = texture2D(tNoise, nUv).r;

    float n = cnoise(vec3(uv * 1.5 * (1.0 - b * 0.5), time*0.6));
    n = smoothstep(-1.0, 0.0, n) * smoothstep(1.0, 0.0, n);
    a *= mix(1.0, n, smoothstep(-0.3, 0.5, length(vUv-0.5)));
    a *= smoothstep(0.0, 0.1, length(vUv-0.5)) * smoothstep(0.5, 0.2, length(vUv-0.5));
    
    //a *= 0.8;
    //a *= smoothstep(0.0, 0.5, a) * smoothstep(1.0, 0.3, a);

    //if (a < 0.01) discard;

    gl_FragColor = vec4(uColor, a);
}{@}CatcherShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tInside;
uniform float uTransparent;
uniform float uDistortStrength;
uniform float uOpacity;
uniform float uOpacity2;

#!VARYINGS

#!SHADER: Vertex

#require(glass.vs)

void main() {
    vec3 pos = position;
    pos.z += uOpacity2*0.1;
    
    setupGlass(pos);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(range.glsl)
#require(glass.fs)

void main() {
    vec3 normal = normalMatrix * (gl_FrontFacing == false ? -vNormal : vNormal);

    gl_FragColor = getGlass(normal);

    vec2 uv = gl_FragCoord.xy / resolution;
    uv += 0.1 * vNormal.xy * gFresnel * uDistortStrength;
    vec3 color = texture2D(tInside, uv).rgb;
    gl_FragColor.rgb = mix(color, mix(gl_FragColor.rgb, color, 1.0 - gl_FragColor.a), 0.5);

    gl_FragColor.a *= uOpacity2 * uOpacity;
}{@}DashedLine.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform float uAlpha;
uniform float uTransition;

#!VARYINGS
varying vec2 vUv2;

#!SHADER: Vertex
void main() {
    vUv2 = uv2;
}

#!SHADER: Fragment
void main() {
    vec2 uv = vUv;
    gl_FragColor = vec4(uColor, uAlpha * float(vUv.x <= uTransition));
}
 {@}OrbShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform float uDepth;
uniform float uOpacity;
uniform float uAlpha;
uniform float uPillar;

uniform sampler2D tMask;
uniform float uFieldOfView;
uniform vec4 quat;
uniform vec2 uShape;
uniform vec3 uVelocity;
uniform vec3 uOffset;
uniform float uLightMultiplier;
uniform highp sampler2D noiseTexture;
uniform vec3 uBackgroundColor;
uniform vec3 uColorCloud0;
uniform vec3 uColorCloud1;
uniform vec3 uColorCloud2;
uniform vec3 uColorCloud3;
uniform float uLightBrightness;
uniform float uLightDecay;
uniform vec3 uLightColor;
uniform float uShadowIntensity;
uniform vec3 uCloudVelocity;
uniform int uSteps;
uniform float uHeight;
uniform float uProgress;
uniform float uUseClouds;

uniform vec3 uLight0;
uniform vec3 uLight1;
uniform vec3 uLight2;
uniform vec3 uLight3;
uniform vec3 uLight4;
uniform vec3 uLight5;
uniform vec3 uLight6;
uniform vec3 uLight7;
uniform vec3 uLight8;
uniform vec3 uLight9;

uniform vec3 uScanLight;
uniform vec3 uBackLight;
uniform float uBackLightIntensity;

#!VARYINGS
varying vec2 vUv;
varying vec3 vNormal;
varying vec4 vMvPos;
varying float vDepth;
varying vec3 vPos;
varying vec4 vMPos;

#!SHADER: OrbShader.vs
void main() {
    vec3 pos = position;
    vPos = pos;
    vMPos = modelMatrix * vec4(pos, 1.0);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);

    vUv = uv;
    vNormal = normalMatrix * normal;
    vMvPos = modelViewMatrix * vec4(pos, 1.0);
    //vDepth = 1.0 - pos.z / uDepth;
}

#!SHADER: OrbShader.fs

#require(fresnel.glsl)
#require(range.glsl)
#require(simplenoise.glsl)
#require(transformUV.glsl)


vec3 uLights[10];


vec3 orientate( vec4 quat, vec3 vec) {
    return  vec + 2.0 * cross( cross( vec, quat.xyz ) + quat.w * vec, quat.xyz );
}

//Fom IÃ±igo Quilez noise.
float noise( in vec3 u ) {
    vec3 x = u ;
    vec3 p = floor(x);
    vec3 f = fract(x);
  f = f*f*(3.0-2.0*f);
  vec2 uv = (p.xy+vec2(37.0,239.0)*p.z) + f.xy;
    vec2 rg = texture(noiseTexture, (uv+0.5)/256.0).yx;
  return mix( rg.x, rg.y, f.z )*2.0-1.0;

}


float map( in vec3 p, int oct ) {
  vec3 q = p  - uVelocity *time;

    float g = 0.5+0.5*noise( q*0.3 );
    
  float f;
    f  = 0.50000*noise( q ); q = q*2.02;
    if( oct>=2 ) 
    f += 0.25000*noise( q ); q = q*2.23;
    if( oct>=3 )
    f += 0.12500*noise( q ); q = q*2.41;
    if( oct>=4 )
    f += 0.06250*noise( q ); q = q*2.62;
    if( oct>=5 )
    f += 0.03125*noise( q ); 
    
    f = mix( f*uShape.x -0.75, f, g*g ) + 0.1;
    return uShape.y *f + uHeight - p.y;
        
}


vec4 getColor(vec3 ro, vec3 rd, vec3 rd2) {

    float t = 0.0;
    float t2 = 0.;
  vec4 acum = vec4(0.0);

    float steps = 0.;
    bool foundOrb = false;

    for( int i=0; i< 400; i++ ) {

       float dt = 0.02;
       float dt2 = 0.001; //This should be an uniform.

       int oct = 5 - int( log2(1.0 + t*0.5) );
       
       vec3 pos = ro + t * rd - uOffset;

       vec3 pos2 = ro + t2 * rd2;

       float density = map( pos, oct );



        if(!foundOrb) {
            for(int j = 0; j < 10; j ++) {

                vec3 ll = uLights[j];

                if(length(ll) > 0.) {

                    vec3 pos2 = ro + t2 * rd2 - vec3(0.) - uOffset;

                    if(length(pos2 - ll) < 0.0195) {
                        foundOrb = true;
                        break;
                    }
                }
            }
        }

       if(foundOrb) break;

       if( density > 0.01 ) {

            vec4 color = vec4(vec3(mix(1., 1. - uShadowIntensity, density)), density);
            float mixer = clamp(density, 0.0, 1.0);
            vec3 mixColor = mix(mix(uColorCloud1, mix(uColorCloud3, uColorCloud0, smoothstep(0.8, 1.8, uProgress)), uProgress*0.2), uColorCloud2, vec3(mixer));
            color.rgb *= mixColor;           
            color.rgb = mix(color.rgb, vec3(0.), 1.0-exp2(-0.1*t));


            for(int j = 0; j < 10; j ++) {

                vec3 ll = uLights[j];

                if(length(ll) > 0.) {
                    ll.x *= 5.;
                    ll.z += 3.;
                    vec3 lightVector = ll - pos - vec3(0.);
                    float lightDecay = abs(dot(normalize(lightVector), vec3(0., 1., 0.)));
                    lightDecay /= pow(1. + (length(lightVector)), uLightDecay);
                    color.rgb += uLightBrightness * vec3(lightDecay) * uLightMultiplier * uLightColor;
                }
            }

            vec3 ll = uScanLight;

            if(length(ll) > 0.) {
                ll.x *= 5.;
                ll.z += 3.;
                vec3 lightVector = ll - pos - vec3(0.);
                float lightDecay = abs(dot(normalize(lightVector), vec3(0., 1., 0.)));
                lightDecay /= pow(1. + (length(lightVector)), uLightDecay);
                color.rgb += uLightBrightness * vec3(lightDecay) * uLightMultiplier * uLightColor;
            }

            ll = uBackLight;

            if(length(ll) > 0.) {
                ll.x *= 5.;
                ll.z += 3.;
                vec3 lightVector = ll - pos - vec3(0.);
                float lightDecay = abs(dot(normalize(lightVector), vec3(0., 1., 0.)));
                lightDecay /= pow(1. + (length(lightVector)), uLightDecay);
                color.rgb += uBackLightIntensity * vec3(lightDecay) * uLightColor;
            }


            color.w    = min(color.w*8.0*dt,1.0);
            color.rgb *= color.a;
            acum += color * (1.0 - acum.a);
       }

       t += dt;
       t2 += dt2;
       steps ++;
       if (acum.a > 0.99 ) break;

    }

    acum = clamp( acum, 0.0, 1.0 );

    return acum;
}


void main() {

    uLights[0] = uLight0;
    uLights[1] = uLight1;
    uLights[2] = uLight2;
    uLights[3] = uLight3;
    uLights[4] = uLight4;
    uLights[5] = uLight5;
    uLights[6] = uLight6;
    uLights[7] = uLight7;
    uLights[8] = uLight8;
    uLights[9] = uLight9;

    float fresnel = getFresnel(normalize(vNormal), vMvPos.xyz, 3.0);

    vec3 color = uColor;

    float noise = cnoise(vUv*2.0+time*0.5);

    if (uPillar < 0.5) {
        color = mix(color, vec3(1.0), 0.4);
        //color = mix(color, vec3(1.0), max(0.0, noise)*0.8);
        color = mix(color, mix(uColor, vec3(1.0), 0.8), smoothstep(0.25, 0.06, fresnel));
        color *= 1.15 + sin(time*2.0+vPos.z*0.5)*0.15;
    }
    

    float alpha = 1.0 * uOpacity;
    alpha *= 0.8 + fresnel * 1.0;
    alpha *= 0.8 + noise*0.3;

    alpha = mix(alpha, 1.0, smoothstep(0.25, 0.06, fresnel));
    float hider = smoothstep(0.2, 0.7, -vPos.z) * smoothstep(6.0, 2.0, -vPos.z);
    if(uUseClouds < 0.5) alpha *= hider;
    alpha *= uAlpha;

    //if (alpha < 0.001) discard;

    gl_FragColor.rgb = alpha * color;
    gl_FragColor.a = alpha;

    //For the clouds
    if (uUseClouds > 0.5) {
        gl_FragColor = vec4(0.);

        vec2 xy = (2.0*gl_FragCoord.xy - resolution.xy)/resolution.y;
        vec4 conj = quat;
        conj.xyz *= -1.;

        float z = resolution.y / tan(radians(uFieldOfView) / 2.0);
        vec3 dir =  normalize(vec3(xy, -z / resolution.y));
        dir = normalize(dir);
        dir = orientate(conj, dir);

        //This is done to evalue the fog for the orbs.
        z = resolution.y / tan(radians(30.) / 2.0);
        vec3 dir2 =  normalize(vec3(xy, -z / resolution.y));
        dir2 = normalize(dir2);
        dir2 = orientate(conj, dir2);

        vec3 eye = vec3(0.);

        //Environment
        vec2 uv = scaleUV(gl_FragCoord.xy / resolution.xy, vec2(1.0, resolution.x/resolution.y));
        vec3 innerColor = mix(uBackgroundColor*0.1, uBackgroundColor*1.1, smoothstep(0.0, 0.8, uProgress));
        innerColor = mix(innerColor, vec3(1.0), smoothstep(0.8, 1.5, uProgress));
        innerColor = mix(innerColor, vec3(1.0), smoothstep(0.98, 1.02, uProgress)*0.2);

        vec3 outerColor = mix(vec3(0.0), uBackgroundColor, smoothstep(0.5, 1.2, uProgress));
        vec3 ambColor = mix(outerColor, innerColor, smoothstep(0.6, 0.0, length(uv-0.5)));

        float rings = fract(length(uv-0.5)*2.0-time*0.5);
        rings = smoothstep(0.4, 0.7, rings) * smoothstep(1.0, 0.7, rings);
        ambColor *= 1.0 + rings*0.1;

        vec4 cloudColor = getColor(eye, dir, dir2);
        cloudColor.rgb += ambColor; 

        float reveal = smoothstep(5.0, 2.0, -vPos.z) * uOpacity * uAlpha;
        vec3 orbColor = mix(vec3(0.9, 0.9, 1.0), cloudColor.rgb , vec3(1. - fresnel));
        orbColor *= 1.15 + sin(time*2.0+vPos.z*0.5)*0.15;

        //for debugging
       // orbColor = vec3(1., 0., 0.);
        
        gl_FragColor.rgb = mix(orbColor, cloudColor.rgb , vec3(cloudColor.a));
        gl_FragColor.rgb = mix(gl_FragColor.rgb, orbColor, reveal);

        //gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(1.0,0.0,0.0), 1.0-uOpacity);

        gl_FragColor.a = smoothstep(0.0, 0.2, reveal);
    }

    if (gl_FragColor.a < 0.01) discard;
}{@}SlowButtonShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec2 uSize;
uniform float uBorder;
uniform vec3 uColor;
uniform float uFill;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment

// float sdBox(vec2 p, vec2 b) {
//     vec2 d = abs(p)-b;
//     return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
// }

// float sdBorder() {
//     float aspect = uSize.y / uSize.x;
//     vec2 nUv = vUv * 2.0 - 1.0;
//     nUv.y *= aspect;

//     vec2 border = vec2(1.0) - uBorder;
//     border.y *= aspect;

//     float d = sdBox(nUv, border);
//     return step(0.0, d);
// }

float condBorder() {
    float b = uBorder;
    float aspect = uSize.y / uSize.x;
    float bX = b * aspect;

    if (vUv.x < bX || vUv.x > (1.0 - bX) || vUv.y < b || vUv.y > (1.0 - b)) {
        return 1.0;
    }

    return 0.0;
}

void main() {
    // float a = sdBorder();
    float a = condBorder();

    float x = abs(vUv.x * 2.0 - 1.0);
    float fill = step(x, uFill);
    a = max(a, fill);

    a *= uAlpha;

    gl_FragColor = vec4(uColor, a);
}{@}StoryTextureShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform sampler2D uTexture;
uniform vec3 uColor;

#!VARYINGS
varying vec2 vUv;

#!SHADER: StoryTextureShader.vs
void main() {
    vUv = uv;
    gl_Position = vec4(position, 1.0);
}

#!SHADER: StoryTextureShader.fs
void main() {
    gl_FragColor = texture2D(uTexture, vUv);
    // gl_FragColor.rgb = uColor;
    gl_FragColor.a = 1.0;
}{@}GameIntroTextShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
// Custom uniform you define and set in the class
uniform vec2 uMouse;
uniform float uOpacity;

#!VARYINGS

#!SHADER: Vertex

#!SHADER: Fragment

// The main function here replaces the default Text3D or override shader
void main() {
    float alpha = msdf(tMap, vUv);
    gl_FragColor.rgb = uColor;
    gl_FragColor.a = alpha * uOpacity;
}{@}GameSelectionViewBackground.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform sampler2D uMap;

#!VARYINGS
varying vec2 vUv;
varying vec3 vNormal;
varying vec4 vMvPos;
varying float vDepth;

#!SHADER: GameSelectionViewBackground.vs
void main() {
    vec3 pos = position;

    gl_Position = vec4(pos, 1.0);

    vUv = uv;
}

#!SHADER: GameSelectionViewBackground.fs

#require(fresnel.glsl)

void main() {
    vec4 texel = texture2D(uMap, vUv);
    gl_FragColor.rgb = texel.rgb;
    gl_FragColor.a = 1.0;
}{@}GameSelectionBG.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor1;
uniform vec3 uColor2;
uniform vec3 uColor3;
uniform float uNoiseScale;
uniform float uNoiseTime;
uniform float uColorMix;
uniform float uHover;
uniform vec3 uHoverColor;

#!VARYINGS
varying vec2 vUv;
varying vec3 vPos;

#!SHADER: Vertex

void main() {
    vUv = uv;
    vec3 pos = position;
    vPos = pos;
    gl_Position = vec4(pos, 1.0);
}

#!SHADER: Fragment

#require(range.glsl)
#require(simplenoise.glsl)
#require(mousefluid.fs)

void main() {
    vec3 color = vec3(0.0);
    vec3 pos = vPos;

    float fluidMask = 0.0;
    float fluidOutline = 0.0;
    vec2 fluid = vec2(0.0);

    #test Tests.renderFluid()
    fluidMask = texture2D(tFluidMask, vUv).r;
    fluidOutline = smoothstep(0.0, 0.3, fluidMask) * smoothstep(1.0, 0.3, fluidMask);
    fluid = texture2D(tFluid, vUv).xy * fluidMask;
    #endtest

    pos.xy += fluid * 0.001;
    pos += uColorMix*0.1;
    
    float timeWarp = time;
    //timeWarp += fluidOutline * 0.5;

    float noise = 0.0;

    noise = cnoise(pos*uNoiseScale+timeWarp*uNoiseTime*0.1+0.0);
    color = mix(color, mix(uColor1, uHoverColor, uHover*0.5), smoothstep(-0.5, 1.5, noise)*uColorMix);

    noise = cnoise(pos*uNoiseScale*0.9+timeWarp*uNoiseTime*0.1+10.0);
    color = mix(color, mix(uColor2, uHoverColor, uHover*0.5), smoothstep(-0.5, 1.5, noise)*uColorMix);

    noise = cnoise(pos*uNoiseScale*1.1+timeWarp*uNoiseTime*0.1+20.0);
    color = mix(color, mix(uColor3, uHoverColor, uHover*0.5), smoothstep(-0.5, 1.5, noise)*uColorMix);

    color += getNoise(vUv,time)*0.005;

    gl_FragColor.rgb = color;
    gl_FragColor.a = 1.0;
}{@}GameSelectionCardBackgroundShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform sampler2D uTexture;
uniform float uTextureFade;
uniform float uScale;
uniform vec2 uRes;
uniform vec2 uTextRes;
uniform vec3 uBorderColor;
uniform float uBorderWidth;
uniform float uExpanded;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;
varying vec3 vNormal;
varying vec4 vMvPos;
varying float vDepth;

#!SHADER: GameSelectionCardBackgroundShader.vs
void main() {
    vec3 pos = position;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);

    vUv = uv;
}

#!SHADER: GameSelectionCardBackgroundShader.fs

#require(fresnel.glsl)
#require(blendmodes.glsl)
#require(transformUV.glsl)

void main() {
    vec2 pos = gl_FragCoord.xy / resolution;
    vec2 uv = scaleUV(vUv, vec2((resolution.x/resolution.y)*(uTextRes.y/uTextRes.x), 1.0));

    uv = scaleUV(uv, vec2(1.0+(1.0-uTextureFade)*0.1));
    pos = mix(pos, uv, 1.0-uExpanded);

    // alpha scale
    float alpha = 1.0;

    vec4 texel = texture2D(uTexture, pos);
    vec3 color = mix(uColor, texel.rgb, uTextureFade);

    vec3 treatment = color;
    treatment = blendOverlay(treatment, uBorderColor*1.1);
    treatment = blendSoftLight(treatment, uBorderColor, 0.3);

    color = mix(color, treatment, (1.0-uExpanded));
    //color = mix(color, blendOverlay(color, vec3(1.0)), smoothstep(0.0, 0.8, uTextureFade)* smoothstep(1.0, 0.8, uTextureFade));

    float borderWidth = uBorderWidth;
    float border = smoothstep(borderWidth+0.001, borderWidth, vUv.x);
    border = max(border, smoothstep(borderWidth+0.001, borderWidth, 1.0-vUv.x));
    borderWidth *= uRes.x/uRes.y;
    borderWidth += (1.0-uScale)*0.5;
    //borderWidth += (1.0-uAlpha) * 0.3;
    border = max(border, smoothstep(borderWidth+0.001, borderWidth, vUv.y));
    border = max(border, smoothstep(borderWidth+0.001, borderWidth, 1.0-vUv.y));
    color = mix(color, uBorderColor, border*uScale*smoothstep(0.5, 0.0, uExpanded));

    alpha = mix(border, 1.0, uTextureFade);
    alpha *= (step(0.5-(uScale)*0.5, (1.0-vUv.y)) * step(0.5-(uScale)*0.5, vUv.y));
    alpha *= (step(0.5-smoothstep(0.0, 0.1, uScale)*0.5, (1.0-vUv.x)) * step(0.5-smoothstep(0.0, 0.1, uScale)*0.5, vUv.x));

    // gl_FragColor.rgb = vec3(d);
    gl_FragColor.rgb = color;
    gl_FragColor.a = alpha;
}{@}IllustrationShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform sampler2D tMap;
uniform vec2 uScale;
uniform vec2 uPosition;
uniform float uAlpha2;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex

void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment
#require(transformUV.glsl)
void main() {
    vec2 uv = vUv;
    uv = scaleUV(uv, uScale, vec2(0.0, 1.0));
    uv += uPosition;

    //uv = scaleUV(uv, vec2(0.8 + uAlpha2*0.2));
     
    vec3 color = texture2D(tMap, uv).rgb;

    color *= uAlpha2;

    gl_FragColor = vec4(color, 1.0);
}{@}DashedLineShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;
uniform float uAlpha;
uniform float uTransition;

#!VARYINGS
varying vec2 vUv;
varying vec3 vPos;

#!SHADER: Vertex

void main() {
    vUv = uv;
    vPos = position;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment

void main() {
    float mod = mod(gl_FragCoord.x * 800. / resolution.x, 10.) > 5.? 1. : 0.;
    float alpha = uAlpha * gl_FragCoord.x * uTransition / resolution.x;
    gl_FragColor = vec4(uColor, alpha);
}{@}GraphBarShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform float uColorVal;
uniform vec3 uColor;
uniform vec2 uSize;
uniform float uRounding;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment
#require(rgb2hsv.fs)

float sdRoundedBox(vec2 p, vec2 b, float r) {
    vec2 q = abs(p) - b;
    return min(max(q.x, q.y), 0.0) + length(max(q,0.0)) - r;
}

void main() {
    vec3 hsv = rgb2hsv(uColor);
    hsv.z *= 0.7 + min(uColorVal, 0.0) * 0.6;
    vec3 color = hsv2rgb(hsv);
    color = mix(color, vec3(1.0), max(uColorVal, 0.0) * 0.5);

    float a = 0.;
    vec2 coords = vUv * uSize;
    vec2 uv = 2. * vUv - 1.;
    uv.y *= uSize.y / uSize.x;

    float h =  (uSize.y - uSize.x )/ uSize.x;
    a = sdRoundedBox(uv, vec2(0., h), 0.);

    float aaf = fwidth(a);
    a = smoothstep(1., 1. - aaf, a);


    a *= pow(1. - vUv.y, 2.);

    float top = length(uv - vec2(0.0, h));
    aaf = fwidth(top);
    top = smoothstep(1., 1. - aaf, top);
    a += top;
    
    a *= uAlpha;

    gl_FragColor = vec4(color, a);{@}GraphPlotShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec2 uSize;
uniform float uLines;
uniform vec3 uColor;
uniform float uAnimate;
uniform float uAlpha;

#!VARYINGS
varying vec2 vUv;

#!SHADER: Vertex
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: Fragment
#define PI 3.141592653589793

void main() {
    float y = fract(vUv.y * uLines + 0.5);

    // float a = 1.0 - smoothstep(0.0, 0.02, y);
    float a = (1.0 - step(0.035, y)) * 0.12;
    // color = mix(vec3(0.0), vec3(1.0), a);

    float slant = sin(uAnimate * PI * 0.5) * vUv.y * 0.6;
    float anim = (1.0 - uAnimate);
    a *= 1.0 - step(1.0, vUv.x + anim - slant);
    a *= uAlpha;

    gl_FragColor = vec4(uColor, a);
}{@}StoryOutroBackgroundShader.glsl{@}#!ATTRIBUTES

#!UNIFORMS
uniform vec3 uColor;

#!VARYINGS
varying vec2 vUv;
varying vec3 vNormal;
varying vec4 vMvPos;
varying float vDepth;

#!SHADER: StoryOutroBackgroundShader.vs
void main() {
    vec3 pos = position;

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);

    vUv = uv;
}

#!SHADER: StoryOutroBackgroundShader.fs

#require(fresnel.glsl)

void main() {
    gl_FragColor.rgb = uColor;
    gl_FragColor.a = 1.0;
}